以前也经常用到指针, 最近一段时间用着用着就懵了, 做下笔记, 以防以后用到会出现这种情况, 本程序在VC上面测试用
下面是C程序:
#include <stdio.h>
typedef struct T_
{
int a;
struct T_* next;
}TB, *TP;
void test_malloc_1(void *p)//不成功
{
p = (void*)malloc(sizeof(TB));
}
void test_malloc_2(void **p)//成功
{
*p = (void*)malloc(sizeof(TB));
((TP)*p)->a = 2;
}
void test_malloc_3(void *p)//成功,此时p中以有成功申请内存的情况下
{
((TP)p)->next = (TP)malloc(sizeof(TB));
((TP)p)->next->a = 3;
}
void test_free_1(void*p)
{
free(((TP)p)->next);
((TP)p)->next = NULL;
free(p);
p = NULL;
}
void test_free_2(void**p)
{
free(((TP)*p)->next);
((TP)*p)->next = NULL;
free(*p);
*p = NULL;
}
int main()
{
void *p = NULL;
test_malloc_1(p);
test_malloc_2(&p);
test_malloc_3(p);
printf("%d, %d\n", ((TP)p)->a, ((TP)p)->next->a);
test_free_1(p);//内存已经被释放, 只是p没有被赋空,p->next被赋空
if(NULL == p)
{
printf("free ok!!\n");
}
test_free_2(&p);//执行到此处会蹦, 因为内存已经被释放
if(NULL == p)
{
printf("free ok!!\n");
}
return 0;
}
C+汇编
//从传参上来讲
43: void *p = NULL;
0040DB08 mov dword ptr [ebp-4],0
44: test_malloc_1(p); //不能成功申请内存
0040DB0F mov eax,dword ptr [ebp-4]
0040DB12 push eax //此处是把p里面装的值, 也就是0, 传进去了
0040DB13 call @ILT+20(_test_b) (00401019)
0040DB18 add esp,4
//跟进函数
p = (void*)malloc(sizeof(TB));
00401058 push 8
0040105A call malloc (00401290)
0040105F add esp,4
00401062 mov dword ptr [ebp+8],eax//此处只是把堆上申请的内存地址编号放在了,栈上面所对应的地址编号上, 并没有放在p中;
test_malloc_2(&p);
lea ecx,[ebp-4]
0040D94E push ecx//传的是地址
0040D94F call @ILT+10(_test_malloc_2) (0040100f)
0040D954 add esp,4
//跟进函数
*p = (void*)malloc(sizeof(TB));
004010A8 push 8
004010AA call malloc (00401290)
004010AF add esp,4
004010B2 mov ecx,dword ptr [ebp+8] //ecx为栈上面的地址编号
004010B5 mov dword ptr [ecx],eax//把堆上申请的内存地址编号, 放在栈上面所对应的地址编号的值为首地址的连续4个字节的内存单元中,即为p;
内存释放:
void test_free_1(void*p)
{
printf("((TP)p)->next: %x \t", ((TP)p)->next);
//free(((TP)p)->next);
//((TP)p)->next = NULL;
printf("p: %x \n", p);
//free(p);
//p = NULL;
}
void test_free_2(void**p)
{
printf("((TP)*p)->next: %x\t", ((TP)*p)->next);
//free(((TP)*p)->next);
//((TP)*p)->next = NULL;
printf("*p: %x", *p);
//free(*p);
//*p = NULL;
}
不管是传一级还是二级指针都是能释放内存的, 它们传进free里面的参数地址是一样的, 唯一的区别是前者不能为指针p赋NULL(p->next是可以的), 后者都可以;
一级指针, 只是把栈上面地址编号所对面的内存=0, 并没有把内存当中存的地址编号的内存=0;
二级指针, 取到栈上面地址编号所对应的内存的值, 再以值为地址取值, 把值=0;
总结:
在申请内存的时候我们定义函数的参数必须为二级, 也就是你要申请内存存放地址编号的地址;
test_malloc_3(void *p)这种情况也可以不用传二级指针, 也能申请成功;
在内存释放的时候我们定义的函数一级二级传递参数的时候内存都能被释放,唯一的不同是一级不能为指针p赋NULL(p->next是可以的), 二级都可以;
307



被折叠的 条评论
为什么被折叠?



