在动态内存分配中,比较经典的错误案例如下:
案例 1:
原代码:
void getmemory(char* p)//应改为char** p
{
p = (char*)malloc(100);//没有把开辟的空间地址传回test函数中的str中
//应改为*p
}
void test(void)
{
char* str = NULL;
getmemory(str);
strcpy(str, "hello world");//str没有指向有效空间,程序崩溃
printf(str);
}
int main()
{
test();
return 0;
}
本段代码运行会出现崩溃的现象,原因如下:
该程序存在内存泄漏的问题,str以值传递的形式传给p,p为getmemory函数的形参,只在getmemory函数内部有效,当getmemory函数返回之后,动态开辟内存尚未释放,并且无法找到,所以存在内存泄露。
改正1:
void getmemory(char **p)
{
*p = (char *)malloc(100);
}
void test(void)
{
char *str = NULL;
getmemory(&str);
strcpy(str, "hello world");
printf(str);
free(str);
str = NULL;
}
int main()
{
test();
return 0;
}
以传址的方式向getmemory函数传str所指向的值,即为**p,在getmemory函数中以指针*p的形式接受malloc函数开辟的空间;
另外添加了内存释放。
改正2:
char* getmemory(char* p)
{
p = (char*)malloc(100);
return p;
}
void test(void)
{
char* str = NULL;
str=getmemory(str);
strcpy(str, "hello world");
printf(str);
free(str);
str = NULL;
}
int main()
{
test();
return 0;
}
在getmemory函数中,增加 <return p> 代码来返回开辟的空间地址,则开辟的空间可以在主函数中进行使用,使用完成后进行释放。
案例 2:
原代码:
char* getmemory(void)
{
char p[] = "hello world";//局部变量,只在此函数内有效
return p;
}
void test(void)
{
char* str = NULL;
str = getmemory();
printf(str);
}
int main()
{
test();
return 0;
}
如代码注释所示,在getmemory函数中定义的变量p为局部变量,无法在其他函数中使用。
相似地:
int* test()
{
int a = 10;//栈区err
return &a;
}
int main()
{
int*p = test();
return 0;
}
上面这段代码中,test函数中定义的整型变量a为局部变量,在栈区存储,无法用于main函数。
将
int a = 10;
改正为:
static int a = 10;
这样变量a存储在静态区,可以被main函数所使用。
改正后的完整代码如下:
int* test()
{
static int a = 10;
return &a;
}
int main()
{
int*p = test();
return 0;
}
相似地:
int* test()
{
int* ptr = malloc(100);//开辟空间在堆区,不free依然存在,可以传回主函数
return ptr;
}
int main()
{
int* p = test();
return 0;
}
上面代码段的指针变量ptr虽然在test函数内部定义,但static定义其为静态指针变量,存储在静态区,不free依然存在于静态区中,可以在main()函数中进行使用。
案例 3:
原代码:
void getmemory(char** p, int num)
{
*p = (char*)malloc(num);
}
void test(void)
{
char* str = NULL;
getmemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
int main()
{
test();
return 0;
}
上面本段代码未释放动态开辟的内存,导致内存泄漏。
在使用完动态内存开辟的空间后,增加以下代码用于释放内存空间:
free(str);//
str = NULL;//此两行代码可以释放空间
改正后的代码如下:
void getmemory(char** p, int num)
{
*p = (char*)malloc(num);
}
void test(void)
{
char* str = NULL;
getmemory(&str, 100);
strcpy(str, "hello");
printf(str);
free(str);//
str = NULL;//此两行代码可以释放空间
}
int main()
{
test();
return 0;
}
案例 4:
原代码:
void test()
{
char* str = (char*)malloc(100);
strcpy(str, "hello");
free(str);
if (str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
int main()
{
test();
return 0;
}
以上的free函数把str指向的的内存空间释放,但不会把str置为NULL,所以下面的if判断语句没有意义。
在if语句前面加上
str = NULL;
改正完成后的代码为:
void test()
{
char* str = (char*)malloc(100);
strcpy(str, "hello");
free(str);//此处把str指向的的内存空间释放,并不会把str置为NULL
str = NULL;
}
int main()
{
test();
return 0;
}
案例4很迷,说不明白,我懂就行了。