【问题标题】:calloc vs new for complicated structs in various compilerscalloc vs new 用于各种编译器中的复杂结构
【发布时间】: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 中,它会导致垃圾。
  • 它真的总是有效运气不好。现在开始修复它。

标签: c++ visual-studio memory-management visual-studio-2017 undefined-behavior


【解决方案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++,使用新的。
猜你喜欢
  • 1970-01-01
  • 2010-11-28
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-30
相关资源
最近更新 更多