内存分配方式有三种: (1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。 (2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。(在函数中不要返回栈内存,但可以返回动态分配的内存)。 (3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。 例子: (1) voidGetMemory(char *p) { p = (char *)malloc(100); } void Test(void) { char *str = NULL; GetMemory(str); strcpy(str, "hello world"); printf(str); } 请问运行Test 函数会有什么样的结果? 答:程序崩溃(段错误)。因为GetMemory 并不能传递动态内存,Test 函数中的str 一直都是 NULL。strcpy(str, "helloworld");将使程序崩溃。 (2) char *GetMemory(void) { char p = "hello world"; return p; } void Test(void) { char *str = NULL; str = GetMemory(); printf(str); } 请问运行Test 函数会有什么样的结果? 答:可能是乱码。 因为GetMemory 返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,新内容不可知。 (3) void GetMemory2(char **p, int num) { *p = (char *)malloc(num); } void Test(void) { char *str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str); } 请问运行Test 函数会有什么样的结果? 答: (1)能够输出hello (2)内存泄漏。 (4) void Test(void) { char *str = (char *) malloc(100); strcpy(str, “hello”); free(str);//没有将str置为NULL, if(str != NULL) { strcpy(str, “world”); printf(str); } } 请问运行Test 函数会有什么样的结果? 答:篡改动态内存区的内容,后果难以预料,非常危险。 因为free(str);之后,str 成为野指针, if(str != NULL)语句不起作用。 ********************************************************************************************** void GetMemory2(char **p, int num) { *p = (char *)malloc(sizeof(char) * num); } void Test2(void) { char *str = NULL; GetMemory2(&str, 100); // 注意参数是 &str,而不是str strcpy(str, "hello"); cout<< str << endl; free(str); } 如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”.由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态内存。 char *GetMemory3(int num) { char *p = (char *)malloc(sizeof(char) * num); return p; } void Test3(void) { char *str = NULL; str = GetMemory3(100); strcpy(str, "hello"); cout<< str << endl; free(str); } ********************************************************************************************** 用函数返回值来传递动态内存这种方法虽然好用,但是常常有人把return 语句用错了。这里强调不要用return 语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡 char*GetString(void) { char p[] = "hello world"; return p; // 编译器将提出警告(告诉你返回的是局部变量) } void Test4(void) { char *str = NULL; str = GetString(); // str 的内容是垃圾 cout<< str << endl; } 用调试器逐步跟踪Test4,发现执行str= GetString 语句后str 不再是NULL 指针,但是str的内容不是“hello world”而是垃圾。 char *GetString2(void) { char *p = "hello world"; return p; } void Test5(void) { char *str = NULL; str = GetString2(); cout<< str << endl; } 函数Test5 运行虽然不会出错,但是函数GetString2 的设计概念却是错误的。因为GetString2 内的“hello world”是常量字符串,位于静态存储区,它在程序生命期内恒定不变。无论什么时候调用GetString2,它返回的始终是同一个“只读”的内存块。 告诉你返回的是一个局部变量,警告。