透过malloc()问题看底层讲解指针

转载请注明原文来自: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

(稍后待续...)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值