C/C++指针内存分配小细节

时间:2021-10-21 14:49:36

char *pc = NULL;

pc = new char[0];

pc[0] = '1';

相信初学者看见上面这段代码,都会觉得奇怪,new char[n]中的n指定给指针变量分配多少内存空间,而n=0时代表什么呢?

其实上面的程序编译、运行都是正确的。因为编译器识别到指定大小为0时,会自动为其分配1BYTE的内存空间。

尝试过的小伙伴会发现,给p[1]赋值也不会报错,原因留到后面讲*1

但是,此时若想用delete [] p; 去释放内存空间就会报错,程序强制中断,因为编译器并没有真正意义上内指针变量分配内存,去释放肯定是不行的。

这就像对一个成功分配内存的指针变量,连续释放两次造成的错误,例子见后面*2

好了,马上看一下成功分配内存的情况是怎么样的。

char *pc = NULL;

pc = new char[5];

pc[0] = '1';

这里的n=5,意味着给指针变量分配5个BYTE内存空间(因类型为char),当然不管是什么类型,指针变量本身均占4BYTE。

先来看上面遗留的第一个问题*1:此时不但可以给p[0]到p[4]赋值,还可以给后面的地址赋值,如p[5],p[10]等。

这就是C/C++完美之余的一个历史遗留缺陷,不进行越界检查。

导致编译没有任何问题,运行阶段有时一不小心也察觉不出,这就要求程序员养成良好的习惯:new后面必出现delete。

若我们在给p[5]或之后的地址赋过值,在运行到delete [] p;语句时,会报错,程序强制中断。错误原因如提示的信息:damage:after normal block。

这就是上面遗留的第二个问题*2:对同一个指针变量指向的内存释放两次,与释放一个没有成功分配内存或引用越界的指针变量类似,都是不允许的。

还有一个值得注意的地方:若new时n>0,delete后只是释放了原来内存地址中对应的值,指针变量仍然指向该内存地址,即:

仍可以赋值、取值进行运算,只是若没有重新赋值,取出的值为不确定值,换句话说就是,p成了传说中的野指针。

所以,这又是一个要求养成良好习惯的地方,看文章开头的地方,声明一个指针但未分配内存空间时,最好将其置为NULL。

这样做有两个好处:1、方便后面进行判断,if(!P){...}表示无内存分配,若当初没有将其置为NULL,则!p为真也代表不了什么;

2、在delete后,重新分配内存之前,将其置回为NULL,避免其成为野指针。

而对于malloc与free,情况类似,有兴趣的小伙伴可以尝试下。

刚开始学习这一块,有哪里不对的地方欢迎大家指出,谢谢!