内存管理 —— 超量写内存
这几天觉得在打 Python 的时候觉得自己欠缺了一点 Data structure 的头脑, 于是去学校图书馆借了一本《算法之美》(是的,书名看起来很民科,但其实内容的深度还是有的)
接下来的时间我打算一点点有选择性地总结一些对我等只学了一点 C 的皮毛的非科班菜鸡有启发的章节
超量写内存是什么问题?
超量写内存,顾名思义,是操作的内存超过了先前开辟的内存,有一点 Overflow 的味道在里面。
即使在一个指针被正确的初始化的前提下,指针运算中的错误,或者错误的内存地址操作,仍然会引起内存管理上的错误。
数组指针的越界访问
当定义一些数组的下标的时候很容易犯这种错,尽管我们早就知道一个数组的下标都是从0开始的。一种常识的选择性遗忘。
容量为array_size
的数组 a 是不存在元素a[array_size]
的,如果用了这个不存在的元素,结果就是可能改变程序里其他数据的值(如果内存中下一个地址也在程序中有另一个定义)
内存分配不足
例1:
#define array_size 10
int *a = new int[array_size];
... ...
int *b = new int[array_size];
... ...
memcpy(b, a, array_size);
看起来没毛病,错在memcpy
的第三个参数应该是数组的物理大小,并不是元素的多少,所以还要乘以 int 类型的字节数:memcpy(b, a, array_size * sizeof(int))
例2:
char *new_string(char *s)
{
int len = strlen(s);
char *new_string = new char[len];
strcpy(new_s, s);
return new_s;
}
字符串结尾有一个隐性的结束符’\0’,因此应该给新字符串分配的内存字节数为len + 1
操作符的优先权
“操作符的优先权也有可能致使程序员访问了不该访问的地址,不慎的使用*和++或—都有可能导致超量写内存”
这一点暂时没有想到如何避免
另一个可能的错误是构造一个指向运行时栈中某值的指针,并将这个指针返回给函数调用者,例如:
int *p()
{
int i = 0;
return &i;
}
这个函数定义的指针在函数返回值后就会出栈而变成毫无意义的随机地址、随机值。