calloc vs new 用于各种编译器中的复杂结构

Posted

技术标签:

【中文标题】calloc vs new 用于各种编译器中的复杂结构【英文标题】:calloc vs new for complicated structs in various compilers 【发布时间】:2017-11-09 13:50:39 【问题描述】:

我有以下结构:

struct MyNewShinyStruct

    int index;
    std::string name;
;

calloc上面的结构然后给name赋值时:

char letters[128]"ABCDEFG";
auto temp = static_cast<MyNewShinyStruct*>(calloc(2, sizeof(MyNewShinyStruct)));
temp[0].name = letters;

我应该为上述问题遇到麻烦:-)(我应该使用new 运算符)。 'calloc' 将分配的内存清零,并且不调用 struct/std::sting 的构造函数。但是,由于某些未知原因,上述代码在 VS2010/2013/2015 中有效,仅在 VS2017 中失败。它应该总是失败!请问我错过了什么?

附: 上面的代码已经投入生产(使用 VS2010 编译)多年,甚至没有一次报告与此代码有关的错误,甚至一次都没有。它总是有效的。

【问题讨论】:

calloc 单独创建非 pod 类型是不够的。 std::string 不是 pod,通过扩展,MyNewShinyStruct 也不是。结果是未定义的行为,无法进行有意义的推理。 未定义的行为并不意味着总是失败。有时它似乎也有效。 它是 C++,使用 std::vector! 您在演示中遗漏的部分是在分配该字符串后打印该字符串的内容。在 Visual Studio 2017 中,它会导致垃圾。 它真的总是有效运气不好。现在开始修复它。 【参考方案1】:

它应该总是失败!请问我错过了什么?

您忽略了 UB 并不意味着“总是失败”这一事实。它可以是任何东西,包括预期的行为。要修复您的程序,请在 calloc 返回的内存上使用placement new(假设您出于某种原因必须使用calloc,如果您不使用std::vector 代替)。您还应该了解std::string 很可能会自行分配内存,除非您提供自定义分配器,否则不太可能 calloc。

【讨论】:

1.我们UB是什么? @RefaelSheinker 未定义行为。 To fix your program use placement new on the memory returned by calloc - 这是一种选择。但我可能会用new 完全替换calloc 并完成它, @RefaelSheinker 你最好使用std::vector,或者至少使用带有new的智能指针 @RefaelSheinker ideone.com/eNQZjc 然后使用placement new .. 注意:您必须手动调用析构函数.. 您让自己更加头疼.. 即使是传统的C++ 也不需要malloc 或 calloc。它是 C++,使用新的。

以上是关于calloc vs new 用于各种编译器中的复杂结构的主要内容,如果未能解决你的问题,请参考以下文章

C ++中的“new”和“malloc”和“calloc”有啥区别? [复制]

C malloc和calloc函数总结

哪个更优化:`new` 或 `calloc`? [复制]

动态分配数组时的C ++ new vs new [] [重复]

剖析C动态内存管理 (malloc,calloc,realloc,柔性数组)

C ++初始化没有New或Malloc / Calloc /等