使用malloc不能返回动态内存
阅读推荐
阅读此篇前可以先阅读:指针变量的传值和传址
GetMemory()的四道经典问题
问题一:malloc 不能返回动态内存
请问运行main 函数会有什么样的结果?
#include <stdio.h>
#include <stdlib.h>
void getmemory(char *p)
{
p=(char *) malloc(100);
strcpy(p,"hello world");
}
int main( )
{
char *str=NULL;
getmemory(str);
printf("%s/n",str);
free(str);
return 0;
}
运行结果:程序崩溃,getmemory中的malloc 不能返回动态内存, free()对str操作很危险。
当参数是指针时容易忽略,请不要用值传递(这样会导致str没有指向分配到的内存),C语言中可以用指针传。
C语言中,没有reference(引用)的概念。这是C规范中规定,之所以大家会认为C语言会有引用,是因为在cpp文件中,支持以c形式写代码。因而导致大家误认为c支持引用。并且很多编译器C/C++是共用的C中有C++代码也能过,有时候C和C++的界限不是很清晰。
C语言是值传递,故在函数调用中修改的值,并不会返传至主调函数。所以原程序在getmemory函数中malloc获得的地址空间的首地址的值只在函数内部有效,函数调用结束后该值就丢失了,传值是把实参的值拷贝给形参,运算中是对形参进行操作,实参的值在运算中不会发生变化。传址是把实参的地址传给形参,运算中是对实参进行操作,会改变实参的值
所以如果考虑使用引用的话,要在函数里返回内存有三种办法:
- 使用指针的指针 **p ,用这个指针指向一个需要分配内存的值。
- 还可以在函数里创造一个指针然后,return他就可以了,这种方法更简单。
- 传引用
正确写法:
#include <stdio.h>
#include <stdlib.h>
void getmemory(char **p)
{
*p=(char *) malloc(100);
strcpy(*p,"hello world");
}
int main()
{
char *str=NULL;
getmemory(&str);
printf("%s/n",str);
free(str);
return 0;
}
//传引用
void getmemory(char &*p)
{
p=(char *) malloc(100); strcpy(p,"hello world");
}
//传址
void getmemory(char **p)
{
*p=(char *)malloc(100); strcpy(*p,"hello world");
}
问题二:GetMemory返回的是指向“栈内存”的指针
请问运行Test 函数会有什么样的结果?
char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
分析:可能是乱码。因为GetMemory 返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原来的内容已经被清除,新内容不可知。
问题三:内存泄漏
请问运行Test 函数会有什么样的结果?
void GetMemory(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
分析:
(1)能够输出hello
(2)内存使用完没有及时通过free释放,造成内存泄漏
关于内存溢出与内存泄漏
- 内存泄漏是指程序在申请内存后,无法释放已申请的内存空间。
- 内存溢出是指程序申请内存时,没有足够的内存供申请者使用;或者说提供一块存储int数据的存储空间,但存储了long数据,则结果是内存不够用,报错OOM。
- 内存泄漏的堆积最终会导致内存溢出
问题四:篡改动态内存区的内容
请问运行Test 函数会有什么样的结果?
void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL)
{
strcpy(str, “world”);
printf(str);
}
}
分析:
篡改动态内存区的内容,后果难以预料,非常危险。因为free(str);之后,str 成为野指针,if(str != NULL)语句不起作用。