内存问题是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')拷贝给了四字节的内存空间,出现内存越界。