Linux 下 c 程序的内存问题

2017-10-25 18:15:10 +08:00
 katsusan
最近碰到了个进程异常中止的问题,core 文件的 gdb 结果看来好像函数的代码区内存被滥用了,类似于如下
(gdb) disass /mr Delete
Dump of assembler code for function Delete():
151 {
→. 0x556ec6b0 <+0>:. 00. 00. add. %al,(%eax)
0x556ec6b2 <+2>:. 00 00. add. %al,(%eax)
...
}
之后的值都是 0x00,统计了下前后总共有 4096 字节的代码区内存被置为 0x00,网上查了下没有提到关于代码转为机器码后的存放问题,是和静态变量它们放在一起还是单独的区域,求各位了解的大佬赐教>:-<
3009 次点击
所在节点    Linux
11 条回复
wevsty
2017-10-25 18:23:45 +08:00
这种情况一般是程序其他地方溢出覆盖了不该覆盖的地方导致的。
katsusan
2017-10-25 18:28:52 +08:00
@wevsty 我原本也是这样想的,但是刚刚查资料提到说程序执行时的代码段区域是只读的,只读区域应该不能被覆盖吗吧
katsusan
2017-10-25 18:29:33 +08:00
@katsusan 多了个“吗”
katsusan
2017-10-25 18:31:32 +08:00
momocraft
2017-10-25 18:42:01 +08:00
Delete 是什麼
katsusan
2017-10-25 18:47:29 +08:00
@momocraft 就是一个普通的函数,
wevsty
2017-10-25 19:06:04 +08:00
@katsusan 事实是可以的。这部分所谓的只读意思是,告诉你不能修改,但是如果你硬要修改是有办法的。毕竟代码同样会被加载到内存上而内存本来就是可读写的。

一般来说,下一条指令要执行的机器码错误多半是由于跳转的地址错误,调用函数实际上要执行 call 指令,而 call 指令是要把 IP ( X86 上是 EIP )寄存器存放到栈空间里的,如果函数里面错误的修改了栈空间里 IP ( EIP )的内容,那么在函数退出的时候 ret 指令就会把错误的值还原到 IP ( EIP ),这样你就会看到下一条执行的指令不正确了。
所以一般来说类似 delete 这种函数执行的时候如果出现这样的问题,多半是因为栈空间进行了错误的写入。仔细检查是否有越界的情况产生。
katsusan
2017-10-25 19:42:21 +08:00
@wevsty 好的,我再检查下,非常感谢
NoAnyLove
2017-10-25 23:04:04 +08:00
正常情况下,如果没有修改代码段的属性,对代码段进行写操作会产生 segmentation fault,除非进行了特殊操作,比如 mprotect
katsusan
2017-10-26 17:13:42 +08:00
@NoAnyLove 哦哦,即使那段代码没执行到的话,修改也会产生 segmentation fault 的吗
NoAnyLove
2017-10-27 00:29:31 +08:00
@katsusan 不需要执行,在写的时候就会触发 segmentation fault

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/400696

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX