新的std::string实现(gcc 5.1)
memcpy on new std::string implementation (gcc 5.1)
我已经写了下面的代码,这似乎是工作良好的旧std::string实现。但是在gcc 5.1中,它崩溃了。
#include <string>
#include <iostream>
#include <cstring>
struct abc
{
public:
abc() {}
abc(const std::string& x)
: gullu(x)
{
}
std::string gullu;
};
int main()
{
abc *a = new abc("dhfghdf");
abc *b = new abc();
memcpy((void *)&b, (void *)&a, sizeof(abc));
std::cout << a->gullu.data() << std::endl;
std::cout << b->gullu.data();
return 0;
}
调试后,我发现在执行memcpy之后,对象'a'的内容变成了垃圾
a构造后,
(gdb) p *a $1 = {gullu = {static npos = 4294967295, _M_dataplus ={> = {<__gnu_cxx::new_allocator> = {},};_M_p = 0x804ea18 "dhfghdf"}, _M_string_length = 7, {_M_local_buf = "dhfghdf 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", _M_allocated_capacity = 1734764644}}
b构造后
memcpy后(gdb) p *b $2 = {gullu = {static npos = 4294967295, _M_dataplus ={> = {& lt; __gnu_cxx:: new_allocator> = {}, }, _ M_p = 0 x804ea38 " "},_M_string_length = 0, {_M_local_buf = 000, _M_allocated_capacity = 0}}}
(gdb) p *a $4 = {gullu = {static npos = 4294967295, _M_dataplus ={> = {<__gnu_cxx::new_allocator> = {},};_M_p = 0x666468}, _M_string_length = 2572404, {_M_local_buf ="t@ 000 030 uy害怕我 215 004 b 001 000 000",_M_allocated_capacity = 2572404}}
(gdb) p *b $5 = {gullu = {static npos = 4294967295, _M_dataplus ={> = {<__gnu_cxx::new_allocator> = {},};_M_p = 0x804ea18 "dhfghdf"}, _M_string_length = 7, {_M_local_buf = "dhfghdf 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00", _M_allocated_capacity = 1734764644}}
我正在使用第三方库,它似乎正在做一个memcpy,它与以前的编译器一起工作,而不是与gcc 5.1一起工作,因为这个问题
有人能帮我一下吗?好吧,你没有做你想做的事。虽然您显然试图将string
的内容复制到另一个,但您正在做的只是将指针(a
)的值复制到另一个(b
),但复制错误的大小!
顺便说一句,你想要的是memcpy(b, a, sizeof(abc));
,但这是不应该工作太(它将在几个情况下工作)!正如我在皮肤上学到的(感谢这个答案),您不能memcpy
具有非平凡初始化的对象。通过重用这样一个对象的存储,你结束了它的生命周期,但只是memcpy
指向它,你不会复活它,所以由b
指向的对象将不是活的。
对象的生存期是对象的运行时属性。一个对象被称为具有非平凡初始化如果它是类或聚合类型,并且它或它的一个成员是由构造函数初始化的,而不是一个平凡的默认构造函数。[注:普通复制/移动构造函数的初始化是非普通初始化。]- - - - - -类型T的对象的生命周期开始于:-获得适合T类型的正确对齐和大小的存储,和如果对象有非平凡初始化,则初始化完成。T类型对象的生命周期在以下情况结束:-如果T是具有非平凡析构函数(12.4)的类类型,则开始析构函数调用,或者- 对象占用的存储空间被重用或释放。§
您正在复制sizeof(abc)
字节的数据,但是您给memcpy的指针指向a
和b
的指针,而不是对象-这个(void*)&a
中的地址绝对是错误的。
但是你真的不应该这样做,因为像这样复制对象而不是使用它们的复制函数或其他适当的方法会导致崩溃和未定义的行为。在这个特定的情况下,如果字符串长一点,可能会发生什么,你最终会有两个string
对象指向同一个堆块,因此你会得到双重删除退出范围,这是一个不可恢复的崩溃。
您的代码触发未定义行为,因为您正在向指针b
的地址复制比指针大小更多的字节:您正在复制sizeof(abc)
而不是sizeof(a)
。
- 理解GCC中的std::pow实现
- 如果不包含 pthread,为什么 GCC 的线程标准库实现会抛出异常?
- 如何实现使用 gcc-4.4 编译的大向量初始化?
- 它是 gcc 中 std::valarray 实现的错误吗?
- 为什么仅 -fno-signed-0 就可以实现优化,而似乎也需要 -ffinite-math-only (gcc)
- GCC 如何实现 C++ 标准分配器
- 有没有比 GCC 或 Clang 实现更直观的方法来在 Linux 的C++中使用内联汇编
- std::chrono::d uration_cast - 是GCC实现的错误
- 在 gcc 上自己的元组实现段错误,同时在 clang 中工作
- 他们实现的开源C编译器(gcc,clang)的实际标准在哪里
- glibc函数的GCC、-flto、-fno内置和自定义函数实现
- 在哪里查找 GCC 实现定义行为的实现?
- GCC 看不到通过多重继承实现
- GCC 4.4 不实现 C++11 范围循环.它还支持哪些其他范围循环语法
- C++,我可以在其中找到 gcc 编译器标准库的实现文件
- std::与VS2013相比,GCC 4.7.2中的MAP实现效率非常低
- 标准::矢量的概念和GCC实现
- 如何为在 .props 文件中声明的非本机 VC 编译器 (GCC) 实现 MSBUILD 文件跟踪功能 (跟踪器.ex
- 重新解释转换行为的GCC实现
- 帮助GCC实现自动矢量化