释放?不释放?实践是检验真理的唯一标准
感谢版主加高亮!发这贴的原因是因为有这一帖 https://bbs.bccn.net/thread-375036-1-1.html
程序代码:
#include <stdio.h> #include <string.h> int main(void) { char a[64] = {0}; strcpy(a, "我用这个数组放一个字符串"); printf("a是:%s\n", a); { //这是个大括号里面 char b[64] = {0}; strcpy(b, a); printf("b是:%s\n", b); } //理论上到这里b就释放了 而且写代码用这个b也确实会出错 return 0; }
GCC 4.6.2 编译参数 gcc a.c -Wall -std=c99
程序代码:
0x004013b7 <main+0>: push ebp 0x004013b8 <main+1>: mov ebp,esp 0x004013ba <main+3>: push edi 0x004013bb <main+4>: push esi 0x004013bc <main+5>: push ebx 0x004013bd <main+6>: and esp,0xfffffff0 0x004013c0 <main+9>: sub esp,0x90 0x004013c6 <main+15>: call 0x40196c <__main> 0x004013cb <main+20>: lea ebx,[esp+0x50] 0x004013cf <main+24>: mov al,0x0 0x004013d1 <main+26>: mov edx,0x40 0x004013d6 <main+31>: mov edi,ebx 0x004013d8 <main+33>: mov ecx,edx 0x004013da <main+35>: rep stos BYTE PTR es:[edi],al 0x004013dc <main+37>: lea eax,[esp+0x50] 0x004013e0 <main+41>: mov edx,eax 0x004013e2 <main+43>: mov ebx,0x408064 0x004013e7 <main+48>: mov eax,0x19 0x004013ec <main+53>: mov edi,edx 0x004013ee <main+55>: mov esi,ebx 0x004013f0 <main+57>: mov ecx,eax 0x004013f2 <main+59>: rep movs BYTE PTR es:[edi],BYTE PTR ds:[esi] 0x004013f4 <main+61>: lea eax,[esp+0x50] 0x004013f8 <main+65>: mov DWORD PTR [esp+0x4],eax 0x004013fc <main+69>: mov DWORD PTR [esp],0x40807d 0x00401403 <main+76>: call 0x40138c <printf> 0x00401408 <main+81>: lea ebx,[esp+0x10] 0x0040140c <main+85>: mov al,0x0 0x0040140e <main+87>: mov edx,0x40 0x00401413 <main+92>: mov edi,ebx 0x00401415 <main+94>: mov ecx,edx 0x00401417 <main+96>: rep stos BYTE PTR es:[edi],al 0x00401419 <main+98>: lea eax,[esp+0x50] 0x0040141d <main+102>: mov DWORD PTR [esp+0x4],eax 0x00401421 <main+106>: lea eax,[esp+0x10] 0x00401425 <main+110>: mov DWORD PTR [esp],eax 0x00401428 <main+113>: call 0x406170 <strcpy> 0x0040142d <main+118>: lea eax,[esp+0x10] 0x00401431 <main+122>: mov DWORD PTR [esp+0x4],eax 0x00401435 <main+126>: mov DWORD PTR [esp],0x408086 0x0040143c <main+133>: call 0x40138c <printf> 0x00401441 <main+138>: mov eax,0x0 0x00401446 <main+143>: lea esp,[ebp-0xc] 0x00401449 <main+146>: pop ebx 0x0040144a <main+147>: pop esi 0x0040144b <main+148>: pop edi 0x0040144c <main+149>: pop ebp 0x0040144d <main+150>: ret
反汇编如上
在整个main()中 堆栈只是在开始和结束的时候动过(sub esp,0x90 lea esp,[ebp-0xc]) 也就是说 所谓的释放是子虚乌有 直到函数返回 堆栈才会释放
以上均为个人意见 仅供参考 不当处望指正 谢谢
==============================偶素华丽的分割线==============================
马上有大牛批评了 立马再试
程序代码:
#include <stdio.h> #include <string.h> int main(void) { char a[64] = {0}; strcpy(a, "我用这个数组放一个字符串"); printf("a是:%s\n", a); { //这是个大括号里面 char b[64] = {0}; strcpy(b, a); printf("b是:%s\n", b); } //理论上到这里b就释放了 char c[64] = "这里再有一个字符串应该是不增加堆栈大小才对"; printf("c是:%s\n", c); return 0; }
编译参数 gcc -Wall -std=c99 a.c
反汇编如下
程序代码:
0x004013b7 <main+0>: push ebp 0x004013b8 <main+1>: mov ebp,esp 0x004013ba <main+3>: push edi 0x004013bb <main+4>: push esi 0x004013bc <main+5>: push ebx 0x004013bd <main+6>: and esp,0xfffffff0 0x004013c0 <main+9>: sub esp,0xd0 0x004013c6 <main+15>: call 0x4019b4 <__main> 0x004013cb <main+20>: lea ebx,[esp+0x90] 0x004013d2 <main+27>: mov al,0x0 0x004013d4 <main+29>: mov edx,0x40 0x004013d9 <main+34>: mov edi,ebx 0x004013db <main+36>: mov ecx,edx 0x004013dd <main+38>: rep stos BYTE PTR es:[edi],al 0x004013df <main+40>: lea eax,[esp+0x90] 0x004013e6 <main+47>: mov edx,eax 0x004013e8 <main+49>: mov ebx,0x408064 0x004013ed <main+54>: mov eax,0x19 0x004013f2 <main+59>: mov edi,edx 0x004013f4 <main+61>: mov esi,ebx 0x004013f6 <main+63>: mov ecx,eax 0x004013f8 <main+65>: rep movs BYTE PTR es:[edi],BYTE PTR ds:[esi] 0x004013fa <main+67>: lea eax,[esp+0x90] 0x00401401 <main+74>: mov DWORD PTR [esp+0x4],eax 0x00401405 <main+78>: mov DWORD PTR [esp],0x40807d 0x0040140c <main+85>: call 0x40138c <printf> 0x00401411 <main+90>: lea ebx,[esp+0x10] 0x00401415 <main+94>: mov al,0x0 0x00401417 <main+96>: mov edx,0x40 0x0040141c <main+101>: mov edi,ebx 0x0040141e <main+103>: mov ecx,edx 0x00401420 <main+105>: rep stos BYTE PTR es:[edi],al 0x00401422 <main+107>: lea eax,[esp+0x90] 0x00401429 <main+114>: mov DWORD PTR [esp+0x4],eax 0x0040142d <main+118>: lea eax,[esp+0x10] 0x00401431 <main+122>: mov DWORD PTR [esp],eax 0x00401434 <main+125>: call 0x4061b8 <strcpy> 0x00401439 <main+130>: lea eax,[esp+0x10] 0x0040143d <main+134>: mov DWORD PTR [esp+0x4],eax 0x00401441 <main+138>: mov DWORD PTR [esp],0x408086 0x00401448 <main+145>: call 0x40138c <printf> 0x0040144d <main+150>: lea edx,[esp+0x50] 0x00401451 <main+154>: mov ebx,0x408098 0x00401456 <main+159>: mov eax,0x2b 0x0040145b <main+164>: mov edi,edx 0x0040145d <main+166>: mov esi,ebx 0x0040145f <main+168>: mov ecx,eax 0x00401461 <main+170>: rep movs BYTE PTR es:[edi],BYTE PTR ds:[esi] 0x00401463 <main+172>: lea ebx,[esp+0x7b] 0x00401467 <main+176>: mov al,0x0 0x00401469 <main+178>: mov edx,0x15 0x0040146e <main+183>: mov edi,ebx 0x00401470 <main+185>: mov ecx,edx 0x00401472 <main+187>: rep stos BYTE PTR es:[edi],al 0x00401474 <main+189>: lea eax,[esp+0x50] 0x00401478 <main+193>: mov DWORD PTR [esp+0x4],eax 0x0040147c <main+197>: mov DWORD PTR [esp],0x40808f 0x00401483 <main+204>: call 0x40138c <printf> 0x00401488 <main+209>: mov eax,0x0 0x0040148d <main+214>: lea esp,[ebp-0xc] 0x00401490 <main+217>: pop ebx 0x00401491 <main+218>: pop esi 0x00401492 <main+219>: pop edi 0x00401493 <main+220>: pop ebp 0x00401494 <main+221>: ret
sub esp,0xd0
是耶非耶
我在下面又定义了一个数组 如果上面大括号里面的数组被【释放】或【重新分配】 则我这个新程序和老程序的堆栈大小应该是一样的 可是呢 并不一样 可见 所谓的大括号可以【释放】内存或【重新分配】内存是子虚乌有的 唯一的功能就是明确这些变量的作用域 而这个功能是比较鸡肋的 因为只能在一个函数内用 比神马 命名空间 差的远罢
再次重申 个人意见 仅供参考
传下exe罢
c99_braces.zip
(50.78 KB)
==============================偶素华丽的分割线==============================
程序代码:
#include <stdio.h> #include <string.h> int main(void) { char a[64] = {0}; strcpy(a, "我用这个数组放一个字符串"); printf("a(%p)是:%s\n", a, a); { //这是个大括号里面 char b[64] = {0}; strcpy(b, a); printf("b(%p)是:%s\n", b, b); } //理论上到这里b就释放了 char c[64] = "这里再有一个字符串应该是不增加堆栈大小才对"; printf("c(%p)是:%s\n", c, c); return 0; }
bash-3.1$ ./c99.exe
a(0022ff00)是:我用这个数组放一个字符串
b(0022fe80)是:我用这个数组放一个字符串
c(0022fec0)是:这里再有一个字符串应该是不增加堆栈大小才对
[ 本帖最后由 zklhp 于 2012-8-11 00:02 编辑 ]