分段错误在结构中分配std :: string

时间:2013-12-08 10:55:15

标签: c++

以下代码在运行时导致细分错误,我无法弄清楚原因:

#include <cstdlib>
#include <string>
#include <iostream>


using namespace std;

struct Token
{
  int num;
  string val;
};


int main()
{
  Token* tok = (Token*) malloc (sizeof(Token));
  tok -> val = "myval";
  std::cout<<tok->val;
}

参见backtrace:

0  0x00007ffff7b95d9b in std::string::assign(char const*, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6;
1  0x0000000000400867 in main ()

3 个答案:

答案 0 :(得分:8)

不要在C ++代码中使用malloc,这很少是正确的选择。

您的选择是:

Token tok;
tok.val = "myval";

auto tok = std::make_unique<Token>(); // C++14
tok->val = "myval";

auto tok = std::unique_ptr<Token>(new Token()); // C++11
tok->val = "myval";

auto tok = std::make_shared<Token>(); // C++11, use if resource is shared
tok->val = "myval";

Token* tok = new Token();
tok->val = "myval";
delete tok;

这些选项应该足以满足大多数情况。

首选从上到下的选项:默认方式应该是创建对象,然后是unique_ptr,然后是shared_ptr,只有在绝对必要时才应该处理原始指针。

原因很简单:异常安全和内存泄漏。对象不能泄露,您不能忘记delete unique_ptrshared_ptr,但您可以使用原始指针。此外,如果发生异常,原始指针将不会被删除。 unique_ptr应该优先shared_ptr,因为shared_ptr有开销(原子计数器使其线程安全)。

演示所有内容编译良好(没有C ++ 14 make_unique):Demo

答案 1 :(得分:6)

malloc不会调用任何构造函数。尝试使用new,它应该可以正常工作。

此后不要忘记delete,或者使用智能指针或直接将变量放在堆栈上。

答案 2 :(得分:4)

Here's why you cannot use malloc with std::string

  

你不能在C ++中使用非平凡的构造函数来malloc一个类。你是什​​么   从malloc获取的是一块原始内存,它不包含   正确构造的对象。任何尝试使用该内存作为   “真正的”对象将失败。

以及(已在其他答案中指出):

  

问题是malloc不会调用示例的构造函数。   由于字符串通常表示为堆栈上的指针,因此   设置为零,并取消引用空指针。你需要使用   而不是新的。

如果你坚持使用malloc,你可以使用placement new(请参阅链接了解详情)或只使用普通的const char*

struct Token
{
  int num;
  const char* val;
};

int main()
{
  Token* tok = (Token*) malloc (sizeof(Token));
  tok->val = "myval";
  std::cout << tok->val;
  free(tok);
} // will not seg fault