您的位置:首页 > 其它

春节小练习——动态内存的传递

2018-02-19 09:51 190 查看
例1:

char *copyName(char *name)
{
char *newname = new char[strlen(name)];
strcpy(newname, name);
return newname;
}

int main()
{
printf("%s\n", copyName("test"));
return 0;
}


copyName()函数中用new分配了堆内存。其内存大小为传入的字符串长度,这里有个bug。由于字符串是以\0作为结束符的,应该多分配一个字节存放\0;否则将修改后面的内存的值,造成无法预料的严重后果;

修改为:char *newname = new char [strlen(name) + 1];

例2:

char *copyName(char *name)
{
char newname[20] = "";
strcpy(newname, name);
return newname;
}

int main()
{
printf("%s\n", copyName("test"));
return 0;
}


copyName()函数中,返回其内数组的地址,由于数组处于栈中,当copyName调用结束后,栈就会被销毁。这里应该返回堆内存地址。

修改为:char *newname = new char [strlen(name) + 1];

内存泄漏

void GetMemory(char *p, int num)
{
p = (char *)malloc(sizeof(char) * num);
}

int main()
{
char *str = NULL;
GetMemory(str, 10);
strcpy(str, "hello");

return 0;
}


这里的GetMemory函数有问题。GetMemory函数体内的p实际上是main函数中的str变量在GetMemory函数栈中的一个备份,因为编译器总是为函数的每个参数制作临时的变量。因此,虽然在在函数体中p申请了堆内存,但是返回到main函数时,str还是NULL,并不指向那块内存,调用strcpy时会导致程序崩溃。

实际上,GetMemory并不能做任何有用的事情。这里还要注意,由于从GetMemory函数返回时不能获得堆中内存的地址,那块堆内存就不能被继续引用,也就得不到释放。因此调用一次GetMemory函数就会产生num字节的内存泄漏。

3种方法解决上面的动态内存不能传递的问题

1、在C语言中,可以通过采用指向指针的指针解决这个问题,可以把str的地址传给函数GetMemory。

2、在C++中,多了一种选择,就是传递str指针的引用。

3、使用函数返回值来传递动态内存。

#include <iostream>
using namespace std;

void GetMemory1(char *p, int num)//错误,内存泄漏
{
p = (char *)malloc(sizeof(char) * num);
}

void GetMemory2(char **p, int num)//正确,二级指针
{
*p = (char *)malloc(sizeof(char) * num);
}

void GetMemory3(char* &p, int num)//正确,传引用
{
p = (char *)malloc(sizeof(char) * num);
}

char *GetMemory4(int num)//正确,函数返回值
{
char *p = (char *)malloc(sizeof(char) * num);
return p;
}

int main()
{
char *str1 = NULL;
char *str2 = NULL;
char *str3 = NULL;
char *str4 = NULL;

//GetMemory1(str1, 20);
GetMemory2(&str2, 20);
GetMemory3(str3, 20);
str4 = GetMemory4(20);

strcpy(str2, "GetMemory 2");
strcpy(str3, "GetMemory 3");
strcpy(str4, "GetMemory 4");

cout << "str2:" << str2 << endl;
cout << "str3:" << str3 << endl;
cout << "str4:" << str4 << endl;

//每当决定不再使用堆内存时,应该释放堆内存
free(str2);
free(str3);
free(str4);

//并把堆内存置空
str2 = NULL;
str3 = NULL;
str4 = NULL;

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: