C语言进阶之内存陷阱
扫描二维码
随时随地手机看文章
看看这段代码有什么问题?
char *DoSomething(...) { char i[32*1024]; memset(i,0,32*1024); ... return i; }
两个重大的问题:
1. 临时变量是通过堆栈实现的,太大的临时变量数组会冲掉堆栈
2. 返回堆栈中的地址是非常危险的,因为堆栈中的值永远是不确定的
看看这段代码有什么问题?
void DoSomething(...) { int i; int j; int k; memset(&k,0,3*sizeof(int)); }
这段代码的作用是将3个临时变量清零
但是这段代码有两个假设:
1. 编译器将i,j,k三个变量通过堆栈表示
2. 压栈顺序是i,j,k(假设堆栈是满递减堆栈)
3. 如果K在寄存器怎么办?对k取地址操作将产生Data Aboart
关于临时变量
不要对临时变量作取地址操作,因为你不知道编译器是否将这个变量映射到了寄存器不要反回临时变量的地址,或临时指针变量,因为堆栈中的内容是不确定的(出了这个函数,存放在堆栈中的局部变量就没有意义了!)不要在申请大的临时变量数组,你的临时变量是在堆栈中实现的,你有多大的堆栈呢?
现在要为一个矩形区或申请一块内存保存这块的数据,如果每个Pixle占用2个bit,如何分配内存?
char *buffer buffer = malloc(x*y/4);×
buffer = malloc(x*y/4+1);
看看这段代码有什么问题?
char *DoSomething(...) { char *p,*q; if((p = malloc(1024)) == NULL) return NULL; if((q = malloc(2048)) == NULL) return NULL; ... return p; }
如果q没有申请到,首先应该释放p,然后再返回NULL!
看看这段代码有什么问题?
void FreeWindoTree(windows *Root) { if(Root != NULL) { windows *pwnd; /*释放pwndRoot的子窗口...*/ for(pwnd = Root->child;pwnd != NULL; pwnd = pwnd->Sibling) FreeWindoTree(pwnd); if(Root->strWndTitle != NULL) FreeMemory(Root->strWndTitle); FreeMemory(Root); } }
pwnd已经被释放了,但是在for循环中被再次引用
关于动态内存
总是检查动态内存是否成功后再引用该指针!在分配struct空间是总是使用sizeof分配内存时宁滥勿缺(别忘了加一)总是Free由malloc()函数返回的指针 按照ANSI C标准Free函数是没有返回值的错误处理时不要忘了其它已经分配空间的释放