我有以下简单程序作为示例:

#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
}

代码可以编译,但是在执行过程中出现段错误:
$ ./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。这是一个弥补的例子。我在调试大量代码时遇到了这个问题,(现在)我对遍历所有malloc并将其替换为new没有兴趣。

我只是想在幕后(基本上是对bt的解释)下理解分配段错误的原因。我当时以为对象* my_str的字符串副本赋值运算符将被调用,并且一切都会正常进行。但是基于结果,我想不是。任何见识将不胜感激。

谢谢,
艾哈迈德。

最佳答案

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 -objects生命周期)。

顺便说一句:constexpr void* operator new(size_t, void*)被定义为仅返回其第二个参数,因此只有new表达式的第二部分,即ctor-call,才有效。

关于c++ - 将取消引用的对象分配给对象会导致段错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27068428/

10-11 22:43
查看更多