将解除引用的对象分配给对象会导致seg错误

时间:2014-11-21 19:01:37

标签: c++ c++11

我有以下简单程序作为说明:

#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的字符串复制赋值运算符,一切都应该解决。但根据结果,我猜不是。任何见解都将不胜感激。

谢谢你, 艾哈迈德。

3 个答案:

答案 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指向的数据设置为字符串对象(指定指向解除引用值的指针)。