gdb地址和“真实”地址之间的区别?

如果我在gdb中运行一个C / C ++程序(在使用-g标志编译之后)并检查某些变量,参数等的地址,然后我在gdb之外运行它(使用./ )将这些地址和我在gdb中看到的一样? 如果它们不同,它们通常是相似的,还是会大不相同?

我问这个是因为我有一个缓冲区溢出程序,它在gdb(有和没有断点)中完美运行,但是当我尝试在gdb之外运行它时它不起作用。

我检查某些变量,参数等的地址,然后我在gdb之外运行它(使用./)这些地址是否与我在gdb中看到的相同

这取决于。

  1. 主可执行文件中定义的全局变量将保留在同一地址(除非可执行文件使用-fpie并与-pie标志链接。
  2. 由于ASLR,在其他共享库中定义的全局变量可能具有截然不同的地址。
  3. 由于ASLR,局部变量和参数可能会移动几个K字节。
  4. 由于ASLR,或者如果您的程序是multithreading的,堆分配的变量也可能会大幅移动。

请注意,默认情况下,Linux上的GDB禁用ASLR,以便更轻松地进行调试。 您可以使用set disable-randomization off在GDB下重新启用ASLR。 这可能允许您在GDB下重现问题。

我有一个缓冲区溢出

另请注意, Valgrind和Address Sanitizer等工具通常比在GDB下运行更有效地查找缓冲区溢出。 地址Sanitizer特别之处在于它在全局和堆栈中找到缓冲区溢出(Valgrind没有)。

您永远不应该假设某个代码或变量将位于固定的位置。

过去在大多数操作系统中都是如此,但这是一个安全漏洞。 恶意软件使用它来传播程序。 操作系统倾向于加扰地址以提高安全性。

使用-g标志进行编译会增加代码大小,因为它会插入可执行的额外信息。

至于你的缓冲区问题,它会有助于发布一些错误的代码片段。