转载请注明原文来自:http://blog.csdn.net/lizhiliang06/article/details/8650070
公司最近来了实习生小明,公司也分配了一个搭档在实习期间带小明,他就是有几年工作经验的大明,
在这段时间,小明遇到过很多问题,也让大明回忆起了刚工作时候的辛酸苦楚,那时候还没有人带大明呢。不过大明经过几年的跌跌撞撞,也总结了不少问题了,有些问题,大明还是可以跟小明讲解的。
你看,现在小明又遇到了问题了,正在那里苦恼呢?究竟是遇到了神马问题了呢?
我们还是一起看吧,小明今天遇到了个malloc()的问题.
展示代码如下:
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <malloc.h>
/*
*错误1
*/
void error_get_mem(char *p, int size)
{
p = (char*)malloc(size*sizeof(char));
}
void main()
{
char *str = NULL;
error_get_mem(str, 20); /*此处为错误的代码函数,仅供对照*/
strcpy(str,"0123456789");
printf("str:%s\n", str);
}
这是错误的呢,在函数里面申请内存,error_get_mem()传入的是一个普通的指针,
在malloc()之后,p这时还只是个局部变量,地址指向申请到的地址区域,但是等
error_get_mem()退栈的时候,就把p给退掉了,可能再也找不到malloc()得到的内存区域了,
那样当然是没有办法成功的给str分配内存成功呢。
正确的做法应该如下:
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <malloc.h>
void right_get_mem(char **p, int size)//p为指针的指针
{
*p = (char*)malloc(size); //*p=str,相当于str = malloc(),改变了指针str指向的内存区域
}
void main()
{
char *str = NULL;
right_get_mem(&str, 20);//把指针的地址传入
strcpy(str,"0123456789");
printf("str:%s\n", str);
}
透过汇编深入看问题:
1: #include <stdio.h>
2: #include <assert.h>
3: #include <string.h>
4: #include <malloc.h>
5:
6: /*
7: *错误1
8: */
9: void error_get_mem(char *p, int size)
10: {
00401020 push ebp //error_get_mem 前先压栈保存原基地址指针ebp, esp+4
00401021 mov ebp,esp //把基地址指针重新定位到堆栈指针
00401023 sub esp,40h // esp - 0x40h,
00401026 push ebx //保存基地址 esp + 4
00401027 push esi //保存源索引地址esp + 4
00401028 push edi //保存目标索引地址esp + 4
00401029 lea edi,[ebp-40h] //回到栈顶
0040102C mov ecx,10h //ecx 设置 10h,在下面将作为循环次数
00401031 mov eax,0CCCCCCCCh //eax 置值0CCCCCCCC
00401036 rep stos dword ptr [edi] //填充值到edi指向的内存
11: p = (char*)malloc(size*sizeof(char));
00401038 mov eax,dword ptr [ebp+0Ch]//把内存地址ebp+0Ch中的双字型(32位)数据赋给eax
0040103B push eax//压栈esp + 4
0040103C call malloc (004010e0)
00401041 add esp,4
00401044 mov dword ptr [ebp+8],eax
12: }
00401047 pop edi
00401048 pop esi
00401049 pop ebx
0040104A add esp,40h
0040104D cmp ebp,esp
0040104F call __chkesp (00403060)
00401054 mov esp,ebp
00401056 pop ebp
00401057 ret
13:
14: void main()
15: {
00401070 push ebp
00401071 mov ebp,esp
00401073 sub esp,44h
00401076 push ebx
00401077 push esi
00401078 push edi
00401079 lea edi,[ebp-44h]
0040107C mov ecx,11h
00401081 mov eax,0CCCCCCCCh
00401086 rep stos dword ptr [edi]
16: char *str = NULL;
00401088 mov dword ptr [ebp-4],0
17: error_get_mem(str, 20); /*此处为错误的代码函数,仅供对照*/
0040108F push 14h
00401091 mov eax,dword ptr [ebp-4]
00401094 push eax
00401095 call @ILT+15(error_get_mem) (00401014)
0040109A add esp,8
18: strcpy(str,"0123456789");
0040109D push offset string "0123456789" (00422f7c)
004010A2 mov ecx,dword ptr [ebp-4]
004010A5 push ecx
004010A6 call strcpy (004030a0)
004010AB add esp,8
19: printf("str:%s\n", str);
004010AE mov edx,dword ptr [ebp-4]
004010B1 push edx
004010B2 push offset string "str:%s\n" (0042201c)
004010B7 call printf (0040d750)
004010BC add esp,8
20: }
(正确代码)
1: #include <stdio.h>
2: #include <assert.h>
3: #include <string.h>
4: #include <malloc.h>
5:
6: void right_get_mem(char **p, int size)
7: {
00401020 push ebp
00401021 mov ebp,esp
00401023 sub esp,40h
00401026 push ebx
00401027 push esi
00401028 push edi
00401029 lea edi,[ebp-40h]
0040102C mov ecx,10h
00401031 mov eax,0CCCCCCCCh
00401036 rep stos dword ptr [edi]
8: *p = (char*)malloc(size);
00401038 mov eax,dword ptr [ebp+0Ch]
0040103B push eax
0040103C call malloc (004010e0)
00401041 add esp,4
00401044 mov ecx,dword ptr [ebp+8]
00401047 mov dword ptr [ecx],eax
9: }
00401049 pop edi
0040104A pop esi
0040104B pop ebx
0040104C add esp,40h
0040104F cmp ebp,esp
00401051 call __chkesp (00403060)
00401056 mov esp,ebp
00401058 pop ebp
00401059 ret
10:
11: void main()
12: {
00401070 push ebp
00401071 mov ebp,esp
00401073 sub esp,44h
00401076 push ebx
00401077 push esi
00401078 push edi
00401079 lea edi,[ebp-44h]
0040107C mov ecx,11h
00401081 mov eax,0CCCCCCCCh
00401086 rep stos dword ptr [edi]
13: char *str = NULL;
00401088 mov dword ptr [ebp-4],0
14: //error_get_mem(str, 20); /*此处为错误的代码函数,仅供对照*/
15: right_get_mem(&str, 20);
0040108F push 14h
00401091 lea eax,[ebp-4]
00401094 push eax
00401095 call @ILT+10(error_get_mem) (0040100f)
0040109A add esp,8
16:
17: strcpy(str,"0123456789");
0040109D push offset string "0123456789" (00422f7c)
004010A2 mov ecx,dword ptr [ebp-4]
004010A5 push ecx
004010A6 call strcpy (004030a0)
004010AB add esp,8
18: printf("str:%s\n", str);
004010AE mov edx,dword ptr [ebp-4]
004010B1 push edx
004010B2 push offset string "str:%s\n" (0042201c)
004010B7 call printf (0040d750)
004010BC add esp,8
19: }
转载请注明原文来自:
http://blog.csdn.net/lizhiliang06/article/details/8650070
(稍后待续...)