我有以下简单程序作为说明:
#include <string>
using namespace std;
int main()
{
string name;
string *my_str;
name = "foo";
my_str = (string *) malloc(sizeof(*my_str));
*my_str = name; // fault line
// my_str = new(my_str) string(name); // fix
}
代码编译,但在执行期间我得到一个seg错误:
$ ./a.out
Segmentation fault (core dumped)
$ gdb -q ./a.out ./core.31114
.....
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 __exchange_and_add_single (__mem=<optimized out>, __val=-1)
at /home/packages/gcc/4.7/w/gcc-4.7-4.7.2/build/x86_64-linux-gnu/libstdc++-v3/include/ext/atomicity.h:66
66 /home/packages/gcc/4.7/w/gcc-4.7-4.7.2/build/x86_64-linux-gnu/libstdc++-v3/include/ext/atomicity.h: No such file or directory.
(gdb) bt
#0 __exchange_and_add_single (__mem=<optimized out>, __val=-1)
at /home/packages/gcc/4.7/w/gcc-4.7-4.7.2/build/x86_64-linux-gnu/libstdc++-v3/include/ext/atomicity.h:66
#1 __exchange_and_add_dispatch (__mem=0xfffffffffffffff8, __val=<optimized out>)
at /home/packages/gcc/4.7/w/gcc-4.7-4.7.2/build/x86_64-linux-gnu/libstdc++-v3/include/ext/atomicity.h:83
#2 std::string::_Rep::_M_dispose (this=0xffffffffffffffe8, __a=...)
at /home/packages/gcc/4.7/w/gcc-4.7-4.7.2/build/x86_64-linux-gnu/libstdc++-v3/include/bits/basic_string.h:242
#3 0x00007fbab7a5ff06 in _M_grab (__alloc1=..., this=<optimized out>, __alloc2=...)
at /home/packages/gcc/4.7/w/gcc-4.7-4.7.2/build/x86_64-linux-gnu/libstdc++-v3/include/bits/basic_string.h:226
#4 _M_grab (__alloc2=..., __alloc1=..., this=<optimized out>)
at /home/packages/gcc/4.7/w/gcc-4.7-4.7.2/build/x86_64-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:244
#5 std::string::assign (this=0x99a040, __str=...) at /home/packages/gcc/4.7/w/gcc-4.7-4.7.2/build/x86_64-linux-gnu/libstdc++-v3/include/bits/basic_string.tcc:251
#6 0x00000000004008b3 in main () at ./strassign.cc:12
我知道问题的解决方法(用字符串“fix”评论的行),我也知道我应该首先使用new。这是一个例子。我在调试大量代码时遇到了这个问题,而且我没有兴趣(目前)通过new替换所有mallocs。
我只是想了解内幕(基本上解释为bt)为什么赋值seg故障。我在想,会调用object * my_str的字符串复制赋值运算符,一切都应该解决。但根据结果,我猜不是。任何见解都将不胜感激。
谢谢你, 艾哈迈德。
答案 0 :(得分:4)
my_str = (string *) malloc(sizeof(*my_str));
这为堆上的string
分配空间(而不是在C ++免费存储上)。
不做的是初始化内存
因此,虽然我们现在有足够的空间来容纳string
,但我们 没有string
。
你的修复
my_str = new(my_str) string(name);
// Should cast the pointer-argument to `void*` before giving it to `new`.
// Otherwise, some other custom overload of `operator new` might match better.
使用placement-new-expression来调用构造函数,并建立对象不变量(从而开始string
- 对象的生命周期)。
BTW:constexpr void* operator new(size_t, void*)
被定义为只返回它的第二个参数,所以只有new-expression的第二部分ctor-call才有效。
答案 1 :(得分:0)
新表达式(如std::string* myString = new myString("hello"));
)执行两个步骤。首先,它为对象分配内存,然后调用构造函数初始化对象。当你使用malloc来分配你的内存时,你拥有对象本身的内存,但它没有以任何方式初始化......只要有任意内存发生在那里。
在std::string
的情况下,实际的字符串数据是单独分配的。分配给对象时,它会尝试将数据复制到对象内部的数据指针中的任何位置,这可能不是你的。
通过调用placement new,您将调用构造函数来初始化您已分别分配内存的对象。
答案 2 :(得分:0)
如果您希望my_str指向与名称相同的数据,那么您想要的是
my_str = &name;
并且不需要malloc。如果要复制它,请使用strcpy(在C中)或您显示的行作为C ++的修复。
现在您正在尝试将my_str指向的数据设置为字符串对象(指定指向解除引用值的指针)。