内存问题是C和C++程序员经常要去面对的问题,常见的内存问题主要有段错误,内存泄漏,越界访问,无效指针等
1、段错误
段错误就是指访问的内存超出了系统给这个程序所设定的内存空间,例如,访问了不存在的内存地址,访问了系统保护的内存地址,访问了只读的内存地址等情况。下面对各种情况举例说明:
#include <stdio.h> #include <stdlib.h> #include <string.h> void loop(){ loop(); } int main() { //段错误情况1,访问了不存在的内存地址 int *p = NULL; *p = 10; printf("%d\n",*p); // //这样写是正确的,因为p1指向了字符串abc的首地址 char* p1 = NULL; p1 = "abc"; printf("%s\n",p1); // //段错误情况2,访问了系统保护的内存地址 int *p2 = (int *)1; //0地址为系统保护内存区域 *p2 = 100; printf("%d\n", *p2); //段错误3,访问了只读的内存地址,这部分段错误为最常见段错误 /* 这里是因为char* str = "abc"是存储在常量区,程序在编译的时候就分配了内存,直到程序结束才释放, 常量区的内容不能被修改,所以一旦尝试去修改就会报段错误 如果定义为char str[] = "abc" 数组存储在变量区,可对内容进行修改,就不会报段错误 */ char *str = "abc"; strcpy(str, "def"); printf("%s\n",str); //段错误4,栈溢出导致的段错误 /* 因为栈内存有限,由编译器自动分配释放,函数的局部变量,函数参数,返回数据,返回地址等都保存再栈空间内, 此处函数形成死循环,函数的地址最终会占满栈空间,x86系统上,内存向下增长,栈溢出到堆区,出现段错误 */ loop(); return 0; }
2、内存泄漏
内存泄漏并不说内存消失,而是内存申请了没有释放,导致这部分内存无法再继续使用的情况,导致了内存的浪费。如果长期内存泄漏就会导致内存溢出,内存用尽,性能不良,而且编译器并不会报错,后期查找问题的根源比较困难,所以一定代码编写时候,避免内存泄漏非常重要。
内存泄漏实例:
#include <stdio.h> #include <stdlib.h> int main () { //内存泄漏 C语言为free的错误使用,C++为delete的错误使用 char *p = (char*) malloc(sizeof(char) * 10); p = 'test'; printf("%s\n", p); free(p); // 此处出现内存泄漏,因为malloc申请的内存地址已经被修改,free的不是malloc申请的内存 //下面为C++的内存泄漏代码 char *p = new char[10]; p = "test"; cout << p << endl; delete[] p; return 0; }
3、内存越界
内存越界使用会引起致命性错误,常见的内存越界有数组越界,如:Int array[10];
array[10] = 10;
还有常见的内存越界问题就是字符串赋值时出现的错误,如:
char buf[4];
strcpy(buf, "test") // 将5字节的字符串(包括'\0')拷贝给了四字节的内存空间,出现内存越界。