以演示样例代码系统的讲述了三种内存损坏的情况: 全局内存、栈损坏及堆损坏, 以及它们产生的原因。
粗略整理例如以下。
Global Memory Corruption
即全局变量的内存使用出了问题,主要还是越界。
例如以下代码:
#include#define MAX 6int arrdata[MAX];int endval;int main(){ int i = 0; endval = 12; for (i = MAX; (endval) && (i >= 0) ; i--, endval--) { arrdata[i] = endval * endval; } printf("Values are \n"); for (i = 0; i < MAX; i++) { printf("\t %d\n", arrdata[i]); } return 0;}
编译运行,输出的结果是:
Values are190441932119600198812016420449
走查代码,你能够发现第一个循环里i的初值是MAX, 应该是MAX-1。
正是这个越界,改写了endval的值。
那个全局变量在内存里是邻居(译注:在我的Mac OS上的输出结果):
(gdb) p &endval$2 = (int *) 0x100001038(gdb) p &arrdata$3 = (int (*)[6]) 0x100001020
所以arrdat[MAX]的赋值操作,实际变成了对endval的赋值。
这种破坏操作能够概括为两种:
- 数组越界,向上或向下(负值).
- 通过指针訪问了错误的地址。
Stack Corruption
在*nix系的系统里,Stack会用来存储局部变量, 函数參数以及返回值。栈损坏经常导致未知的行为及崩溃。
栈损坏有两种情况:
- 内存越界操作。
- 栈溢出(stack overflow)。
内存越界
越界的情况和之前类似,仅仅是发生在了栈存储的数据上。比方以下的代码 :
#include#include #define LEN 6void cpyPrint(char *str){ char aBuf[LEN]; strcpy(aBuf, str); printf("String is %s\n", aBuf);}int main(){ char *aStr = "MyLinux"; cpyPrint(aStr); return 0;}
编译运行就会崩溃。
以下是在我的Mac OS上的结果:
(gdb) rStarting program: /Volumes/Development/Project/Testing/stackcorruptReading symbols for shared libraries +.............................. doneProgram received signal SIGABRT, Aborted.0x00007fff88815d46 in __kill ()(gdb) bt#0 0x00007fff88815d46 in __kill ()#1 0x00007fff8602d053 in __abort ()#2 0x00007fff85fee74d in __chk_fail ()#3 0x00007fff85feea1f in __strcpy_chk ()#4 0x0000000100000ea6 in cpyPrint (str=0x100000f3e "MyLinux") at stackcorrupt.c:8#5 0x0000000100000ef3 in main () at stackcorrupt.c:17
原因在cpyPrint函数中的局部变量大小为6,却要放进去8个字符(包含一个结束符)。
栈溢出
以下是栈溢出问题的演示样例代码:
#includeint recur(long int var){ if (var > 0) { recur (var--); } printf("the var is %ld\n", var); return var;}int main(){ recur (3000); return 0;}
这段代码什么时候崩。还要看在运行的系统里的栈大小的设置,能够使用以下的指令直接查到:
$ulimit -s
默认情况下会是8192 (KBytes)。
Heap Corruption
出现堆错误。会报臭名昭著的Segment Fault错误。产生的原因有三种:
- 尝试向已经释放的内存写入数据。
- 越界操作 (的确是最常见的原因)。
- 尝试向尚未分配的内存写入数据。
以下是一个演示样例:
#include#include int main(){ int *pData = NULL; int num = 12; pData = (int*) malloc (num * sizeof (int)); //...do stuff use the memory free(pData); pData[0] = -1; pData = (int*) malloc (num * sizeof (int)); //...do stuff use the memory free(pData); return 0;}
要想排查内存问题,首选工具自然是Valgrind了,不多做介绍了。
原因链接: