发生Segfault,GDB中断,但在segfault之后运行行没有显示违规

时间:2013-04-25 14:46:02

标签: gdb segmentation-fault

我有一个特定行的segfaulting程序:

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

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

(gdb)p smaller_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++;
    }

    ...
}

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

2 个答案:

答案 0 :(得分:1)

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

您将large_base和smaller_base递增1并将结果地址转换为u64 *。 如果size是以字节为单位,那么你应该检查large_base + index + 8&lt;大小

答案 1 :(得分:0)

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