【问题标题】:Segfault occurs, GDB breaks on line, but running line after segfault shows no violation发生Segfault,GDB断线,但segfault后跑线显示没有违例
【发布时间】:2013-04-19 12:49:19
【问题描述】:

我有一个程序在特定行出现段错误:

uint64_t small_num = *(uint64_t*)(smaller_base+index);

GDB 成功捕获了允许我调试问题的段错误。但是,如果我从 GDB 提示符运行该行,则不会发生内存访问冲突:

(gdb) p small_num = *(uint64_t*)(smaller_base+index)

谁能提供一些关于如何调试这个问题的建议?我不知所措,因为我验证了 small_base+index 处的内存存在。会不会是选角的问题?

提前致谢。

编辑:提供更多代码,但实际上就是这么简单。我已经大量编辑代码以显示索引的要点。

uint64_t ** find_difference(unsigned char * larger_base,
                              uint64_t size,
                              unsigned char * smaller_base,
                              uint64_t tmap_size)
{
    uint64_t len = size < tmap_size?size:tmap_size;
    uint64_t index=0;
    while(index<len)
    {
            uint64_t larger_num = *(uint64_t*)(larger_base+index);
            uint64_t smaller_num = *(uint64_t*)(smaller_base+index);
            if(larger_num > smaller_num)
            {
                ... do stuff
            }
            index++;
    }

    ...
}

Edit#2:现在我正在考虑它,指针解引用是否可能超出 len?据我了解,x86 数字是从高地址到低地址存储的。因此在内存中,数字 0x01020304 存储为 0x04 0x03 0x02 0x01。它是否正确?如果这不是真的,那么尊重将超出缓冲区的末尾。但是,在 GDB 中,我验证了该地址是可访问的。

【问题讨论】:

  • 上下文中的更多代码会对我们有所帮助。
  • 请详细说明smaller_base和index类型。

标签: gdb segmentation-fault


【解决方案1】:

您的原始指针算法将 index 添加到 (unsigned char *) 之前,然后将其转换为 uint64_t 导致未对齐的内存负载,即尝试从不是 8 的倍数的地址中取消引用 (uint64_t *)。这在调试器中有效,但会在您的程序中导致 SEGFAULT。

【讨论】:

    【解决方案2】:

    我不知道你是怎么使用find_difference()函数的,以及传递给函数的参数的值是什么,但是我怀疑你的指针算法是错误的。

    您将 large_base 和 small_base 加 1 并将结果地址转换为 u64*。 如果 size 以字节为单位,那么您应该检查 large_base+index+8

    【讨论】:

    • size 是以字节为单位的缓冲区大小。我认为您的评论与我第二次编辑的问题相似,并且是正确的。对于 index = size-1,索引将使用缓冲区末尾之后的 8 个字节。我会验证并返回。呸,就是这么简单,多谢多一双眼睛。
    • 确认我的指针数学搞砸了会检查右手边界。
    猜你喜欢
    • 2011-02-08
    • 2013-05-30
    • 1970-01-01
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 2012-09-15
    • 2021-08-12
    相关资源
    最近更新 更多