欢迎光临
我们一直在努力

C/C++指针与内存的常见错误踩坑

C/C++指针与内存的常见错误踩坑

  • 一、常见错误
    • 1、野指针
    • 2、内存泄漏
    • 3、缓冲区溢出
    • 4、空指针解引用
    • 5、双重释放
    • 6、指针类型不匹配
    • 7、忘记初始化指针
    • 8、指针没有指向一块合法的内存
    • 9、没有为结构体指针分配足够的内存
    • 10、为指针分配的内存太小
    • 11、内存越界
  • 二、代码示例

在这里插入图片描述

一、常见错误

1、野指针

  • 原因:指针在内存被释放后继续使用,导致指向无效地址。
  • 后果:程序行为未定义,可能崩溃或数据损坏。
  • 示例代码:#include <stdlib.h>
    int main() {
    int *ptr = (int *)malloc(sizeof(int));
    *ptr = 10;
    free(ptr); // 内存释放
    *ptr = 20; // 错误:ptr现在指向无效内存(野指针)
    return 0;
    }
  • 避免方法:在释放内存后将指针设为NULL,并在使用前检查指针有效性。

2、内存泄漏

  • 原因:动态分配的内存未被释放,导致程序占用内存持续增长。
  • 后果:长期运行的程序可能耗尽系统内存。
  • 示例代码:#include <stdlib.h>
    void leak_example() {
    int *ptr = (int *)malloc(sizeof(int));
    *ptr = 5;
    // 忘记释放ptr,内存泄漏
    }
    int main() {
    leak_example();
    return 0;
    }
  • 避免方法:确保每个malloc或new都有对应的free或delete。在C++中,使用智能指针(如std::unique_ptr)自动管理内存。

3、缓冲区溢出

  • 原因:访问数组或缓冲区时超出其分配边界。
  • 后果:可能覆盖相邻内存,导致数据损坏、安全漏洞(如栈溢出攻击)。
  • 示例代码:#include <string.h>
    int main() {
    char buffer[5];
    strcpy(buffer, "HelloWorld"); // 错误:写入超出buffer大小
    return 0;
    }
  • 避免方法:使用安全函数如strncpy代替strcpy,并检查数组索引范围。

4、空指针解引用

  • 原因:尝试访问或修改空指针(NULL或nullptr)指向的内容。
  • 后果:程序通常崩溃(segmentation fault)。
  • 示例代码:int main() {
    int *ptr = NULL;
    *ptr = 10; // 错误:解引用空指针
    return 0;
    }
  • 避免方法:在使用指针前检查是否为NULL,并确保初始化指针。

5、双重释放

  • 原因:同一内存块被释放多次。
  • 后果:内存管理数据结构损坏,可能导致程序崩溃。
  • 示例代码:#include <stdlib.h>
    int main() {
    int *ptr = (int *)malloc(sizeof(int));
    free(ptr);
    free(ptr); // 错误:双重释放
    return 0;
    }
  • 避免方法:释放内存后将指针设为NULL,避免重复释放。

6、指针类型不匹配

  • 原因:指针类型与指向的数据类型不一致,如将int*强制转换为char*后错误访问。
  • 后果:数据解释错误或对齐问题。
  • 示例代码:int main() {
    int num = 10;
    char *cptr = (char *)&num; // 强制转换
    *cptr = 'A'; // 可能只修改部分字节,导致未定义行为
    return 0;
    }
  • 避免方法:避免不必要的指针类型转换,使用正确的类型。

7、忘记初始化指针

  • 原因:指针未初始化就使用,可能指向随机地址。
  • 后果:未定义行为,可能崩溃或安全风险。
  • 示例代码:int main() {
    int *ptr; // 未初始化
    *ptr = 5; // 错误:指向无效地址
    return 0;
    }
  • 避免方法:始终初始化指针为NULL或有效地址。

8、指针没有指向一块合法的内存

  • 原因:定义了指针变量,但是没有为指针分配内存

  • 后果:未定义行为,可能崩溃或安全风险。

  • 示例代码:

    struct student
    {
    char *name;
    int score;
    }stu,*pstu;

    int main()
    {
    strcpy(stu.name,'Jimy');
    stu.score = 99;
    return 0;
    }

  • 避免方法:记得使用malloc分配内存。

9、没有为结构体指针分配足够的内存

  • 原因:为结构体分配了内存,但是没有给结构体内部成员指针分配内存

  • 后果:可能崩溃或安全风险。

  • 示例代码:

    struct student
    {
    char *name;
    int score;
    }stu,*pstu;
    int main()
    {
    pstu = (struct student*)malloc(sizeof(struct student*));
    strcpy(pstu->name,'Jimy');
    pstu->score = 99;
    free(pstu);
    return 0;
    }

  • 避免方法:记得只要是指针都需要使用malloc分配内存。

10、为指针分配的内存太小

  • 原因:字符串后面有个结束符没有计算入大小。

  • 后果:可能崩溃或安全风险。

  • 示例代码:

    int main()
    {
    char *p1 = “abcdefg”;
    char *p2 = (char *)malloc(sizeof(char)*strlen(p1));
    strcpy(p2,p1);
    return 0;
    }

  • 避免方法:字符串结尾有结束符\\0所以strlen后的长度要加1。

11、内存越界

  • 原因:内存分配成功,且已经初始化,但是操作越过了内存的边界。

  • 后果:可能崩溃或安全风险。

  • 示例代码:

    int main()
    {
    int a[10] = {0};
    for(uint8_t i=0;i<=10;i++)
    {
    a[i] = i;
    }
    return 0;
    }

  • 避免方法:for 循环的循环变量一定要使用半开半闭的区间,而且如果不是特殊情况,循环变量尽量从0 开始。

二、代码示例

错误代码

#include <stdlib.h>

void createArray() {
int *arr = (int *)malloc(5 * sizeof(int)); // 分配内存给一个包含5个整数的数组
if (arr == NULL) {
// 处理分配失败
return;
}
for (int i = 0; i < 5; i++) {
arr[i] = i; // 初始化数组
}
// 函数结束,但没有释放 arr 指向的内存
// free(arr); // 缺少这行,导致内存泄漏
}

int main() {
createArray(); // 调用函数
return 0;
}

错误分析

  • 错误原因:在 createArray 函数中,使用 malloc 分配了内存,但在函数返回前没有调用 free(arr) 来释放内存。每次调用该函数时,都会分配新的内存块,但程序无法再访问这些内存(因为没有指针指向它),导致内存泄漏。
  • 后果:如果程序多次调用 createArray,内存使用量会持续增加,最终可能导致系统内存不足、程序变慢或崩溃。
  • 常见场景:内存泄漏在长期运行的程序(如服务器或GUI应用)中尤其危险,也容易在循环或递归中发生。

修复方法 要修复内存泄漏,必须在不再需要内存时显式释放它。以下是修复后的代码:

#include <stdlib.h>

void createArray() {
int *arr = (int *)malloc(5 * sizeof(int));
if (arr == NULL) {
return;
}
for (int i = 0; i < 5; i++) {
arr[i] = i;
}
// 使用完毕后释放内存
free(arr); // 添加释放操作
}

int main() {
createArray();
return 0;
}

修复说明 添加 free(arr) 确保在函数退出前释放内存。在C++中,可以使用智能指针(如 std::unique_ptr)自动管理内存,避免手动释放。

在这里插入图片描述

赞(0)
未经允许不得转载:171主机测评 » C/C++指针与内存的常见错误踩坑
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址