关闭

编写高质量代码:改善C++程序的150个建议(连载14)

发表于:2012-4-20 09:46

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:李健    来源:51Testing软件测试网采编

  第3章 说一说“内存管理”的那点事儿

  在C++的世界里,“烫”和“屯”是我们遇到得最多的两个汉字(限于VC用户)。可能有人不禁要问:这是为什么呢?

  答案是:在VC中,栈空间未初始化的字符默认是-52,补码是0xCC。两个0xCC ,即0xCCCC在GBK编码中就是“烫”;堆空间未初始化的字符默认是-51,两个-51在GBK编码中就是“屯”。 二者都是未初始化的内存。

  C++赋予了我们直接面对内存、操作内存的能力,但是内存管理却一直以来被认为是C++语言的一大难点。因为在C++语言中,缺少GC(垃圾回收器),内存管理需要程序员手动完成,并且还要为可能的失误承担后果。

  正如下面的“代码故事”:

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. /*  
  4.    在经历过无数的"烫烫烫烫烫","屯屯屯屯屯屯"之后,  
  5.    我们都知道了:内存原来是可以驾驭的...  
  6. */  
  7. int main()  
  8. {  
  9.    /*  
  10.       原来内存管理是这样的,即便结果完美无缺,  
  11.       但却危机四伏...  
  12.    */  
  13.    const char *src="Hello Csdn!";  
  14.    char *dest=(char*) malloc(strlen(src));  
  15.    memcpy(dest,src,strlen(src)+1);  
  16.    printf("%s\n",dest);  
  17.    return 0;  
  18. }  
  19. /*  
  20.   代码结束了,故事也到此为止。但是我们要做的还很多。  
  21.   希望我们能少遇到一点烫和屯...  
  22. */

  所以,我们要说说内存管理那点事儿,争取早日练就内存管理的高深技艺。

  建议27:区分内存分配的方式

  在C/C++语言中,用内存管理的水平去划分高手与菜鸟已经成为一种不成文的约定:可以从中获得更好的性能、更大自由的被称作C++高手,而程序经常面临着莫名其妙的崩溃,一遍遍的调试,费时又费力的则可能是菜鸟级别的。而这一切都源于那让人又爱又恨的C++内存管理的灵活性。其中,多样的内存分配方式就是其灵活性的最好例证之一。

  一个程序要运行,就必须先将可执行的程序加载到计算机内存里,程序加载完毕后,就可以形成一个运行空间,并按照图3-1所示的那样进行布局。

  代码区(Code Area)存放的是程序的执行代码;数据区(Data Area)存放的是全局数据、常量、静态变量等;堆区(Heap Area)存放的则是动态内存,供程序随机申请使用;而栈区(Stack Area)则存放着程序中所用到的局部数据。这些数据可以动态地反应程序中对函数的调用状态,通过其轨迹也可以研究其函数机制。其中,除了代码区不是我们能在代码中直接控制的,剩余三块都是我们编码过程中可以利用的。在C++中,数据区又被分成自由存储区、全局/静态存储区和常量存储区,再加上堆区、栈区,也就是说内存被分成了5个区。这5种不同的分区各有所长,适用于不同的情况。

  栈(Stack)区

  在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元将自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是所分配的内存容量有限。

  堆(Heap)区

  堆就是那些由new分配的内存块,其释放编译器不会管它,而是由我们的应用程序控制它,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统就会自动回收。

41/41234>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号