使用 gdb 调试断言显示奇怪的 std::string 大小

问题描述 投票:0回答:1

我在 C++ 程序中遇到断言问题。

HA_Archive & HA_Archive::operator << (const string & str) {
    buffer[wcursor] = HA_TYPE_STRING;
    wcursor++;
    unsigned size = str.size();
    CASSERT((bufferSize > wcursor + size),"buffer exceeds the maximum");

CASSERT 是一个简单的断言,存在问题。

程序留下了一个核心转储,我用gdb调试过,我发现了一些奇怪的东西。

Program terminated with signal 6, Aborted.
#0  0xb7766424 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7766424 in __kernel_vsyscall ()
#1  0xb6cd1cb1 in raise () from /lib/libc.so.6
#2  0xb6cd33e8 in abort () from /lib/libc.so.6
#3  0xb6ccb58c in __assert_fail () from /lib/libc.so.6
#4  0x086c6dbd in HA_Archive::operator<< (this=0xb2610fb8, str=@0xb49e1f08) at HA_Archive.cxx:94
#5  0x0849b4d3 in PortDriver::serialize (this=0xb49e1ed8, ar=@0xb2610fb8) at PortDriver.cxx:624
#6  0x0838ed80 in PortSession::serialize (this=0xb49e1630, ar=@0xb2610fb8) at PortSession/PortSession.h:71

(gdb) frame 4
#4  0x086c6dbd in HA_Archive::operator<< (this=0xb2610fb8, str=@0xb49e1f08) at HA_Archive.cxx:94
94  HA_Archive.cxx: No such file or directory.
    in HA_Archive.cxx
(gdb) print str
$1 = (const string &) @0xb49e1f08: {static npos = 4294967295, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0xb322f9b4 "NOT-SET"}}
(gdb) print wcursor
$2 = 180
(gdb) print bufferSize
$3 = 4096
(gdb) print size
$4 = 171791040

打印str我可以看到它有“NOT-SET”,这没关系,但是当我打印变量sizestr.size()时,值是巨大的!显然是断言失败的原因,因为 bufferSize 是 4096 而 wcursor 只有 180。

我距离 gdb 专家还很远,所以我的第一个问题是我是否做错了什么。也许大小不是运行时的真实值?

我的第二个问题是:如果 gdb 显示了正确的大小值,为什么我在打印时正确地看到了字符串“NOT-SET”,但大小却是那么大?

c++ gdb assert coredump
1个回答
0
投票

有几种方法可以实现这一点。

字符串确实可能是这个大小,但内容可能在 str[7] 处有一个 nul 字符,这将导致 GDB 停止打印它。

或者可能有什么东西在你的堆上乱写乱画,并覆盖了存储字符串大小的内存位置,所以虽然内容仍然只有 7 个字节长,但 size 成员已被垃圾覆盖。

或者

str
可能只是一个悬空引用,并且
_M_p
指向的内存仍然包含字符串“NOT-SET”,但包含 size 成员的内存已被重新用于其他用途。

我会尝试在 valgrind 下运行,以确保不存在可能覆盖成员的缓冲区溢出或释放后使用错误。

© www.soinside.com 2019 - 2024. All rights reserved.