std::string::assign() 导致段错误
我有一个 std::vector
,其中包含特定偏移量的字符串。这是一个缩短的转储:
...
@128 00 00 00 00 00 00 00 00 73 6F 6D 65 74 68 69 33 ........somethin
@144 38 36 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ng..............
@160 00 00 00 00 00 00 00 00 31 2E 32 2E 33 00 00 00 ........1.2.3...
@176 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
...
我试图提取偏移量 136 处的数据并将其放入 std::string
中:
std::string x;
x.assign(vec.begin()+136, vec.begin()+168);
但是,这会导致我的应用程序出现段错误。现在我对 Linux 下的软件开发还很陌生,但我确实知道如何在 GDB 中启动我的应用程序并获得回溯,并在此处跟踪问题:
(gdb) backtrace
#0 0xb7536d78 in ?? () from /lib/i686/cmov/libc.so.6
#1 0xb7538cd5 in malloc () from /lib/i686/cmov/libc.so.6
#2 0xb7708957 in operator new(unsigned int) () from /usr/lib/libstdc++.so.6
#3 0xb76e4146 in std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) () from /usr/lib/libstdc++.so.6
#4 0xb76e63b0 in std::string::_M_mutate(unsigned int, unsigned int, unsigned int) () from /usr/lib/libstdc++.so.6
#5 0xb76e654a in std::string::_M_replace_safe(unsigned int, unsigned int, char const*, unsigned int) () from /usr/lib/libstdc++.so.6
#6 0x0806d651 in std::string::_M_replace_dispatch<__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > > > (this=0xbfffe464, __i1=..., __i2=..., __k1=..., __k2=...) at /usr/include/c++/4.3/bits/basic_string.tcc:637
#7 0x0806d26e in std::string::replace<__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > > > (this=0x811c730, vec=...) at /usr/include/c++/4.3/bits/basic_string.h:1390
#8 std::string::assign<__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > > > (
this=0x811c730, vec=...) at /usr/include/c++/4.3/bits/basic_string.h:958
#9 myclass::somemethod (this=0x811c730, vec=...) at myclass.cpp:135
打印 vec.size() 返回 200甚至循环遍历向量并打印数据也不会给我带来任何问题(正好在崩溃的片段之上!)。
我正在 Debian 中使用 g++ 4.3.4 进行编译。关于这个问题可能是什么的任何指示吗?
I have a std::vector<uint8_t>
that contains strings at specific offsets. Here's a shortened dump:
...
@128 00 00 00 00 00 00 00 00 73 6F 6D 65 74 68 69 33 ........somethin
@144 38 36 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ng..............
@160 00 00 00 00 00 00 00 00 31 2E 32 2E 33 00 00 00 ........1.2.3...
@176 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
...
I am trying to extract the data at offset 136 and put it into a std::string
:
std::string x;
x.assign(vec.begin()+136, vec.begin()+168);
This however, causes my application to segfault. Now I'm pretty new at software development under Linux, but I do know how to start my app in GDB and get a backtrace, and tracked the problem down here:
(gdb) backtrace
#0 0xb7536d78 in ?? () from /lib/i686/cmov/libc.so.6
#1 0xb7538cd5 in malloc () from /lib/i686/cmov/libc.so.6
#2 0xb7708957 in operator new(unsigned int) () from /usr/lib/libstdc++.so.6
#3 0xb76e4146 in std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) () from /usr/lib/libstdc++.so.6
#4 0xb76e63b0 in std::string::_M_mutate(unsigned int, unsigned int, unsigned int) () from /usr/lib/libstdc++.so.6
#5 0xb76e654a in std::string::_M_replace_safe(unsigned int, unsigned int, char const*, unsigned int) () from /usr/lib/libstdc++.so.6
#6 0x0806d651 in std::string::_M_replace_dispatch<__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > > > (this=0xbfffe464, __i1=..., __i2=..., __k1=..., __k2=...) at /usr/include/c++/4.3/bits/basic_string.tcc:637
#7 0x0806d26e in std::string::replace<__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > > > (this=0x811c730, vec=...) at /usr/include/c++/4.3/bits/basic_string.h:1390
#8 std::string::assign<__gnu_cxx::__normal_iterator<unsigned char const*, std::vector<unsigned char, std::allocator<unsigned char> > > > (
this=0x811c730, vec=...) at /usr/include/c++/4.3/bits/basic_string.h:958
#9 myclass::somemethod (this=0x811c730, vec=...) at myclass.cpp:135
Printing vec.size()
returns 200 and even looping over the vector and printing the data causes me no problems (exactly above the crashing snippet!).
I am compiling in Debian with g++ 4.3.4. Any pointers on what this problem could be?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的代码中其他地方可能存在不匹配的释放/删除,导致症状延迟到现在。当您使用释放的内存时,只要操作系统认为合适,操作系统就可以继续运行。
尝试在 valgrind 中运行该程序。 valgrind 使用自己的 malloc 和 free,因此它可以提醒您错误的消息和删除。确保在没有优化的情况下编译并使用
-g
1:确保不要从超出范围的堆栈变量创建指针。例如,这是新开发人员中的一个常见错误:
由于 a 超出了范围,因此您将返回指向已释放内存的指针。
1关于
-g
,来自联机帮助页:以操作系统的本机格式(stabs、COFF、XCOFF 或 DWARF 2)生成调试信息。 GDB 可以使用此调试信息。There is likely a mismatched free/delete somewhere else in your code that is delaying the symptom until now. When you use freed memory, the operating system is free to continue as long as it sees fit.
Try running the program in valgrind. valgrind uses its own malloc and free so it can alert you to incorrect news and deletes. Make sure to compile without optimisations and with
-g
1:Make sure you to do not create a pointer from a stack variable that goes out of scope. For example, this is a common mistake among newer developers:
As a has gone out of scope, you are returning a pointer to freed memory.
1About
-g
, from the manpage: Produce debugging information in the operating system's native format (stabs, COFF, XCOFF, or DWARF 2). GDB can work with this debugging information.