函数的参数是一个指针,不要用该指针去申请动态内存
void get_memory(char *p, int num)
{
p = (char *)malloc(sizeof(char) * num);
}
void main(void)
{
char *str = NULL;
str = get_memory(str, 20);
strcpy(str, "Hello, world");
}
可以得到str依旧是NULL。
编译器总是为每个函数的参数提供一个临时副本,指针参数p的副本看做是_p,编译器使得_p=p,如果函数体内的程序修改了_p指向的内容,同样,就导致参数p指向的内容也做相应的修改(它们指向同一块内存区域)。这也是指针可以用作输出参数的原因。但是上例中,_p申请了新的内存,只是把_p本身的值修改了,即指向了新的内存空间,但是p本身没有做丝毫修改(即修改_p本身的值而不是_p指向的对象)。
解决办法;
(1) 指向指针的指针或指针的引用
void get_memory(char **p, int num)
{
*p = (char *)malloc(sizeof(char) * num); //动态分配的存储空间不在函数栈上,调用结束该空间不会被释放
}
void test1(void)
{
char *str = NULL;
str = get_memory(&str, 20);
strcpy(str, "Hello world");
cout<<str<<endl;
free(str);
}
(2) 函数返回值传递动态内存(但是return语句返回指向“栈内存”的指针或引用就不行,因为该内存在函数结束时将自动释放)
char *get_string(void)
{
char p[] = "Hello world"; //切记,这是在栈空间开辟的内存,调用结束就会释放该空间
return p;
}
void test(void)
{
char *str = NULL;
str = get_string();
cont<<str<<endl;
}
跟踪调试上面的例子,发现str不在是NULL;但str的内容也非“Hello world”,而是垃圾。
char *get_string1(void)
{
char *p = "Hello world";
return p;
}
void test2(void)
{
char *str = NULL;
str = get_string1();
cout<<str<<endl;
}
上面的例子虽然没有出错,但是p指向的静态存储区域,“Hello world”是字符串常量,它的生命周期在程序结束前始终有效,无论什么时候调用get_string1(),返回的始终是同一个“只读的内存区域”,不可试图修改它,因此,可以将返回值修改为const char *类型以避免程序无意修改字符串常量。