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

为什么C++中向结构体添加std::string后用malloc分配内存会崩溃?

报错根源

该异常是因为你混用了C的内存分配函数malloc和包含非POD成员的C++结构体:

  • std::string不属于普通旧数据类型,内部维护了动态分配的字符指针,必须通过构造函数完成初始化才能正常读写。你的Test结构体包含std::string成员,因此也属于需要构造函数初始化的非POD类型。
  • malloc仅负责分配指定大小的堆内存,不会执行任何构造函数逻辑,你通过malloc申请到的Test数组内存是完全未初始化的,内部的std::string成员的指针指向调试模式下填充的无效标记值0xCDCDCDCD,偏移后就是你看到的0xCDCDCDD1。
  • 执行a[0] = Test()赋值时,会调用std::string的拷贝赋值运算符,尝试访问未初始化的无效指针地址,因此触发读访问权限异常。
    之前结构体没有std::string时属于纯POD类型,不需要构造函数初始化,直接赋值不会访问非法内存,因此运行正常。
修复方案

以下三种方案任选即可:

  • 方案一:改用C++的new运算符分配数组,new会在分配内存后自动调用每个元素的构造函数
int main()
{
    Test* a = new Test[2];
    a[0] = Test();
    std::cout << "Hello World!\n";
    // 用完记得调用delete[]释放内存,避免泄漏
    delete[] a;
    return 0;
}
  • 方案二:如果必须使用malloc分配内存,可以通过定位new手动调用构造函数初始化对象
#include <iostream>
#include <string>
#include <new> // 必须包含该头文件使用定位new

struct Test {
    Test() {}
    std::string name;
};

int main()
{
    Test* a;
    a = (Test*)malloc(2 * sizeof(Test));
    // 手动调用每个元素的构造函数完成初始化
    new (&a[0]) Test();
    new (&a[1]) Test();
    
    a[0] = Test();
    std::cout << "Hello World!\n";
    
    // 用完需要先手动调用析构函数,再释放内存
    a[0].~Test();
    a[1].~Test();
    free(a);
    return 0;
}
  • 方案三:使用std::vector管理动态数组,自动处理内存分配、构造和析构逻辑,更安全不易出错
#include <iostream>
#include <string>
#include <vector>

struct Test {
    Test() {}
    std::string name;
};

int main()
{
    std::vector<Test> a(2);
    a[0] = Test();
    std::cout << "Hello World!\n";
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 06:45:05