You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

动态分配二维C-string数组访问与修改异常问题排查

嘿,这个问题我太熟悉了——咱们来一步步拆解哪里出问题,以及怎么修复:

核心问题:你覆盖了动态分配的指针,还指向了同一个缓冲区

你一开始的动态分配逻辑是对的:

for (int i = 0; i < n_names; i++)
    names[i] = new char[SPACE_FOR_EACH_NAME];

这确实给每个子数组分配了独立的内存空间。但后面你执行这句的时候出了大问题:

names[count-1] = (char*) current.c_str();

这里你做了两件坏事:

  1. 直接覆盖了之前动态分配的指针:原来names[count-1]指向你刚new出来的内存,现在你把它换成了current.c_str()返回的指针——这直接导致之前分配的内存再也没法释放,造成了内存泄漏。
  2. 所有索引都指向同一个内存地址:current是同一个std::string对象,每次调用std::getline都会更新它内部的字符缓冲区,而c_str()返回的指针始终指向这个缓冲区的起始位置。所以不管你给names的哪个索引赋值,最终所有元素都指向同一块内存,最后一次输入的内容自然会覆盖之前的,导致输出两次最后那个名字。

另外还要提一句:std::string::c_str()返回的是const指针,你用(char*)强制转换去掉const是不安全的,而且这个指针的有效期只到current的内容被修改或者它被销毁之前,完全不适合用来长期保存。

修复方案:复制内容到动态分配的内存里

你需要把current中的字符串内容复制到之前分配好的char数组中,而不是直接赋值指针。可以用C标准库的strncpy(记得包含<cstring>头文件)来做安全的复制:

修改后的输入循环应该是这样:

#include <cstring> // 别忘了加这个头文件

// ...

int count = 0;
while (count < n_names) {
    std::cout << "Name " << ++count << ": ";
    std::getline(std::cin, current);
    // 复制current的内容到已分配的内存,最多复制SPACE_FOR_EACH_NAME-1个字符(留位置存结束符)
    strncpy(names[count-1], current.c_str(), SPACE_FOR_EACH_NAME - 1);
    // 手动添加字符串结束符,防止strncpy在源字符串过长时不自动添加
    names[count-1][SPACE_FOR_EACH_NAME - 1] = '\0';
}

额外注意点

  • 为什么用strncpy而不是strcpy?因为strcpy不会检查目标数组的大小,如果输入的名字超过SPACE_FOR_EACH_NAME-1,会造成缓冲区溢出,而strncpy可以限制复制的字符数,更安全。
  • 必须手动添加'\0':如果源字符串长度等于或超过SPACE_FOR_EACH_NAME-1,strncpy不会自动在目标数组末尾加结束符,这样后续遍历字符串的时候会读到垃圾数据。
  • 修复后,你之前的内存释放逻辑就能正常工作了,不会再出现内存泄漏。

现在再运行代码,输入两个不同的名字,就能正常输出各自的内容啦!

内容的提问来源于stack exchange,提问作者BMendes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 08:18:09