C++实战之内存管理

来源:互联网 发布:古典吉他好学吗 知乎 编辑:程序博客网 时间:2024/04/29 06:14
常见的内存分配和使用错误
 
1)        内存的申请和分配并没有成功,但程序员却使用了它。一些新手经常会犯这种错误,他们并不会留意到内存没有分配成功。判断指针的值是否为NULL可以有效地避免这种错误。
2)        内存的分配已经成功,但是却没有进行初始化就直接使用它了。首先是观念上的问题,很多人都没有在使用指针前要初始化这样的习惯,然而这个习惯却是很重要的,希望大家一定要强迫自己养成。第二就是主观地认为自己申请的内存的缺省值为0,这样想是没有什么道理的,内存分配后的值是不确定的。
3)        上面的两种工作都已经做好了(已经成功申请并初始化完成),但是操作时却越界了。
4)        申请了内存,使用完了却忘记了释放,导致内存泄露。这样的错误可以形容为一个恶性的肿瘤,它不会马上要你的命,但是它会慢慢地吞噬你的系统资源,直到你的程序彻底完蛋。
5)        你很小心地释放了内存,但是却又使用了它。由于程序很复杂或者调用顺序出错,这样可能导致出现上面的错误。
 
指针---一把伟大的双刃剑
 
我真的非常佩服发明指针的人,他简直太伟大了。能使用如此简洁地方法将复杂的内存结构描述的如此清楚,这本身就是一种伟大的成就。但是,指针之于程序员如同武器之于士兵,用好了可以威力无比,用不好则害人害己。
我先说说指针和数组的区别。数组名对应着一块内存,它的地址、容量在其生命周期中是不可变的,只有数组内容是可变的。指针可随时指向任何类型的内存,它的特点就是“变”。指针远比数组灵活,但也更危险。
数组名是不能直接进行赋值和比较的。如果你向要将数组a赋值给数组b,不能直接用赋值语句b = a ,这样会令编译器产生错误的。必须使用标准的库函数strcpy来进行赋值。相同地,要比较a和b的内容是否相同,不能使用普通的逻辑判断if(b==a),也要应用库函数strcmp来判断。
//数组……
char a[] = “hello”;
char b[100];
strcpy(b, a);            // b = a is wrong
if (strcmp(b, a) == 0)       //if (b == a) is wrong
       cout<<b<<endl;
//指针……
int len = strlen(a);
char *p = (char *)malloc(sizeof(char)*(len+1));
strcpy(p, a);
if (strcmp(p, a) == 0)
       cout<<p<<endl;
free(p);
在计算内存容量的时候有一点是必须要指出的,那就是sizeof计算数组是计算它的实际的内存容量,而计算指针时则永远都是4个字节。C++是永远没有办法直到指针所指的内存容量,除非在申请时记住它。
 
free和delete如何对付指针?
 
程序员都知道它们是用来释放申请的内存的,但是却很少有人注意到指针本身并没有发生什么变化。各位可以在VC中使用单步跟踪一下,你们会惊奇地发现当指针p被调用了free后它的地址值并没有改变,只是该地址对应的内存中原来有意义的值变成了垃圾,“p”却还是指向的这块内存。记住,一定要第一时间将p的值设为NULL,否则会让别人以为p是一个有意义的指针而误使用它(当别人使用该指针时会判断指针的值是否为NULL,如果不为NULL就会以为它有意义)。
char *p = (char *)malloc(100);
strcpy(p, “hello”);
free(p);                     // the address of  “p” is not changed.
….
if (NULL != p)       //it will return TRUE
       strcpy(p, “world”);        //Wrong!!!
下面提两点,让大家可以防止上面的情况出现:
1)        指针声明后要马上初始化。因为指针出现的缺省值是随机的,所以一定要赋值为NULL,然后再使用。
2)        调用了free和delete后一定要将指针赋值为NULL。原因上面已经提过了,就不再赘述了。
 
原创粉丝点击