请问运行Test函数会有什么样的结果?

____Zhang 2011-03-18 10:12:13
void GetMemory(char *p)
{
p = (char *)malloc(100);
}

void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, "hello world");
printf(str);
}

在网上看到的一道题,答案是运行Test会使程序崩溃。因为GetMemory并不能传递动态内存,Test函数中的str一直都是NULL,strcpy(str, "hello world");将使程序崩溃。

GetMemory并不能传递动态内存,这句很迷糊,难道是所有的函数都不能传递动态内存吗?
...全文
674 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2011-03-18
  • 打赏
  • 举报
回复
去掉编译选项“/GZ 启用堆栈检查(/RTCs堆栈帧运行时检查)”后更简洁些:
1:    #include <stdio.h>
2: #include <stdlib.h>
3: #include <string.h>
4: void GetMemory(char *p) {
//00401030 55 push ebp
//00401031 8B EC mov ebp,esp
//00401033 83 EC 40 sub esp,40h
//00401036 53 push ebx
//00401037 56 push esi
//00401038 57 push edi
5: p = (char *)malloc(100);
//00401039 6A 64 push 64h
//0040103B E8 90 00 00 00 call malloc (004010d0)
//00401040 83 C4 04 add esp,4
//00401043 89 45 08 mov dword ptr [ebp+8],eax
6: }
//00401046 5F pop edi
//00401047 5E pop esi
//00401048 5B pop ebx
//00401049 8B E5 mov esp,ebp
//0040104B 5D pop ebp
//0040104C C3 ret
7: void Test(void) {
//00401060 55 push ebp
//00401061 8B EC mov ebp,esp
//00401063 83 EC 44 sub esp,44h
//00401066 53 push ebx
//00401067 56 push esi
//00401068 57 push edi
8: char *str = NULL;
//00401069 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0
9: GetMemory(str);
//00401070 8B 45 FC mov eax,dword ptr [ebp-4]
//00401073 50 push eax
//00401074 E8 8C FF FF FF call @ILT+0(_GetMemory) (00401005)
//00401079 83 C4 04 add esp,4
10: strcpy(str, "hello world");
//0040107C 68 1C 00 42 00 push offset string "hello world" (0042001c)
//00401081 8B 4D FC mov ecx,dword ptr [ebp-4]
//00401084 51 push ecx
//00401085 E8 56 1F 00 00 call strcpy (00402fe0)
//0040108A 83 C4 08 add esp,8
11: printf(str);
//0040108D 8B 55 FC mov edx,dword ptr [ebp-4]
//00401090 52 push edx
//00401091 E8 CA 1E 00 00 call printf (00402f60)
//00401096 83 C4 04 add esp,4
12: }
//00401099 5F pop edi
//0040109A 5E pop esi
//0040109B 5B pop ebx
//0040109C 8B E5 mov esp,ebp
//0040109E 5D pop ebp
//0040109F C3 ret
13: void main() {
//004010B0 55 push ebp
//004010B1 8B EC mov ebp,esp
//004010B3 83 EC 40 sub esp,40h
//004010B6 53 push ebx
//004010B7 56 push esi
//004010B8 57 push edi
14: Test();
//004010B9 E8 51 FF FF FF call @ILT+10(_Test) (0040100f)
15: }
//004010BE 5F pop edi
//004010BF 5E pop esi
//004010C0 5B pop ebx
//004010C1 8B E5 mov esp,ebp
//004010C3 5D pop ebp
//004010C4 C3 ret
赵4老师 2011-03-18
  • 打赏
  • 举报
回复
VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编并单步执行一遍不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”
1:    #include <stdio.h>
2: #include <stdlib.h>
3: #include <string.h>
4: void GetMemory(char *p) {
//00401030 55 push ebp
//00401031 8B EC mov ebp,esp
//00401033 83 EC 40 sub esp,40h
//00401036 53 push ebx
//00401037 56 push esi
//00401038 57 push edi
//00401039 8D 7D C0 lea edi,[ebp-40h]
//0040103C B9 10 00 00 00 mov ecx,10h
//00401041 B8 CC CC CC CC mov eax,0CCCCCCCCh
//00401046 F3 AB rep stos dword ptr [edi]
5: p = (char *)malloc(100);
//00401048 6A 64 push 64h
//0040104A E8 E1 00 00 00 call malloc (00401130)
//0040104F 83 C4 04 add esp,4
//00401052 89 45 08 mov dword ptr [ebp+8],eax
6: }
//00401055 5F pop edi
//00401056 5E pop esi
//00401057 5B pop ebx
//00401058 83 C4 40 add esp,40h
//0040105B 3B EC cmp ebp,esp
//0040105D E8 5E 1F 00 00 call __chkesp (00402fc0)
//00401062 8B E5 mov esp,ebp
//00401064 5D pop ebp
//00401065 C3 ret
7: void Test(void) {
//00401080 55 push ebp
//00401081 8B EC mov ebp,esp
//00401083 83 EC 44 sub esp,44h
//00401086 53 push ebx
//00401087 56 push esi
//00401088 57 push edi
//00401089 8D 7D BC lea edi,[ebp-44h]
//0040108C B9 11 00 00 00 mov ecx,11h
//00401091 B8 CC CC CC CC mov eax,0CCCCCCCCh
//00401096 F3 AB rep stos dword ptr [edi]
8: char *str = NULL;
//00401098 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0
9: GetMemory(str);
//0040109F 8B 45 FC mov eax,dword ptr [ebp-4]
//004010A2 50 push eax
//004010A3 E8 5D FF FF FF call @ILT+0(_GetMemory) (00401005)
//004010A8 83 C4 04 add esp,4
10: strcpy(str, "hello world");
//004010AB 68 1C 00 42 00 push offset string "hello world" (0042001c)
//004010B0 8B 4D FC mov ecx,dword ptr [ebp-4]
//004010B3 51 push ecx
//004010B4 E8 C7 1F 00 00 call strcpy (00403080)
//004010B9 83 C4 08 add esp,8
11: printf(str);
//004010BC 8B 55 FC mov edx,dword ptr [ebp-4]
//004010BF 52 push edx
//004010C0 E8 3B 1F 00 00 call printf (00403000)
//004010C5 83 C4 04 add esp,4
12: }
//004010C8 5F pop edi
//004010C9 5E pop esi
//004010CA 5B pop ebx
//004010CB 83 C4 44 add esp,44h
//004010CE 3B EC cmp ebp,esp
//004010D0 E8 EB 1E 00 00 call __chkesp (00402fc0)
//004010D5 8B E5 mov esp,ebp
//004010D7 5D pop ebp
//004010D8 C3 ret
13: void main() {
//004010F0 55 push ebp
//004010F1 8B EC mov ebp,esp
//004010F3 83 EC 40 sub esp,40h
//004010F6 53 push ebx
//004010F7 56 push esi
//004010F8 57 push edi
//004010F9 8D 7D C0 lea edi,[ebp-40h]
//004010FC B9 10 00 00 00 mov ecx,10h
//00401101 B8 CC CC CC CC mov eax,0CCCCCCCCh
//00401106 F3 AB rep stos dword ptr [edi]
14: Test();
//00401108 E8 02 FF FF FF call @ILT+10(_Test) (0040100f)
15: }
//0040110D 5F pop edi
//0040110E 5E pop esi
//0040110F 5B pop ebx
//00401110 83 C4 40 add esp,40h
//00401113 3B EC cmp ebp,esp
//00401115 E8 A6 1E 00 00 call __chkesp (00402fc0)
//0040111A 8B E5 mov esp,ebp
//0040111C 5D pop ebp
//0040111D C3 ret
software工程师 2011-03-18
  • 打赏
  • 举报
回复
额,想看看效果,用VC6编译不过...
str一直没有分配到空间,函数GetMemory里只是给形参p分配了空间,这跟str无关,test()里操作strcpy函数就会出问题,这里编译能过吗?
suzhiwei411 2011-03-18
  • 打赏
  • 举报
回复
楼上的,应该是str指针复制了一份传递给了p,然后执行完getmemory之后就释放掉了,test函数中的str并没有获得内存,str的值仍然是null吧?而不是把NULL值复制一份给p吧
LinuxBirdMan 2011-03-18
  • 打赏
  • 举报
回复
指针也是一个值。。传指针。。其实也是把指针地址复制过去一份。。。这里相当于把NULL值复制一份给p。。。p是局部变量。。用完之后没有释放。。。所以内存泄露。。。之后又对str进行操作。。。
pengzhixi 2011-03-18
  • 打赏
  • 举报
回复
因为str并没有得到malloc分配的内存地址,仅此而已。
LinuxBirdMan 2011-03-18
  • 打赏
  • 举报
回复
内存泄露。。。。。对NULL指针进行写操作。。系统崩溃。。。

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧