以下代码在运行时导致细分错误,我无法弄清楚原因:
#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 ()
答案 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_ptr
或shared_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