我有以下简单程序作为示例:
#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/