【问题标题】:Why does the address of a local variable vary when executing multiple times, but not when debugging it with GDB?为什么一个局部变量的地址在多次执行时会发生变化,而用GDB调试时却没有?
【发布时间】:2011-10-11 01:25:02
【问题描述】:

为什么从 gdb 运行代码时,声明的变量的地址相同,但在执行二进制文件时,我没有得到相同的地址。

#include<stdio.h>
void main()
{
    int *x,q;
    //I saw the address of the variable q in this program through gdb during the __1st__ execution.
    //I re-compiled the program to make x to point to this address.
    x=0x7fffffffe2bc; 
    *x=3;
    printf("%d",(*x));
}

我通过 gdb 运行程序,它从未出现过 Segfault。

$ gdb -q ./a.out  
Reading symbols from /home/eknath/needed2/a.out...done.  
(gdb) r  
Starting program: /home/eknath/needed2/a.out   
3
Program exited normally.  
(gdb) q  
$

但程序的正常执行总是会产生 SEGFAULT。

$ ./a.out   
Segmentation fault

我不知道这个问题是否与Is this always the address for GDB debug program?重复

注意:我没有关闭 ASLR

【问题讨论】:

标签: c memory-management gdb


【解决方案1】:

在 GDB 下运行时,局部变量总是得到相同地址的原因是 GDB(为了简化大多数调试场景)禁用了地址空间随机化。

您可以通过set disable-address-randomization off 要求 GDB不要这样做。

出于好奇,为当前进程禁用地址随机化确实不需要需要任何特权,并且通过调用personality(2) 来完成。这是添加此功能的patch

【讨论】:

    【解决方案2】:

    编辑:让我澄清一下我的观点,因为它可能还不清楚。 GDB 默认禁用 ASLR,因此您的变量将始终具有相同的地址(除非代码发生更改,在某些情况下在之前甚至之后添加变量或代码可能会导致分配的地址发生偏移并导致失败)。这样你的代码就成功了,因为在 GDB 中运行时硬编码的地址将在同一个位置。这有助于调试,因为地址不会随着调试会话而改变。

    【讨论】:

    • 这么有效,gdb 关闭了 ASLR?
    • 是的,还有其他一些事情,但对于您的问题,ASLR 是重要的一点。它还只允许 2 个并发线程(旧版本至少不能谈论新的)并且还有一些其他限制。
    • 但我不明白它是怎么做到的。我的意思是只能通过 sysctls 或其他特权方式设置/取消设置 ASLR,对吗?没有 root 权限或 setuid 的 gdb 如何做到这一点?
    • GDB 在其实现中使用 ptrace,并且在跟踪进程时可以设置选项。
    • 哦,很好。你能给我看一些官方文件吗?我想更详细地了解这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-06
    • 2021-05-15
    • 2021-12-18
    • 2012-11-18
    • 1970-01-01
    • 2020-10-23
    • 2020-01-15
    相关资源
    最近更新 更多