【问题标题】:Failed to call standard math function inside debugger?无法在调试器中调用标准数学函数?
【发布时间】:2017-03-03 05:45:23
【问题描述】:

我尝试在调试器中调用自己的函数和标准函数:

#include<stdlib.h>
#include<math.h>
#include<stdio.h>
int i=3;
void f(){
  ++i;
  printf("%d\n",i);
}
int main(){
  ++i;
  int j=i+2;
  double d=cos(0.0);
  printf("%f\n",d);
  return 0;
}

编译这个程序并运行,它会像我预期的那样打印“1.000000”。 在 gdb 中,我尝试过:

(gdb) b main
Breakpoint 1 at 0x40055b: file x.c, line 10.
(gdb) r
Starting program: /home/x/a.out 

Breakpoint 1, main () at x.c:10
10    ++i;
(gdb) call f()
4
(gdb) call f()
5
(gdb) call cos(0.0)
No symbol "cos" in current context.  # WHY?????
(gdb) call printf("%d\n",i)
5
$1 = 2
(gdb) call putchar('a')
$2 = 97

为什么 gdb 甚至找不到符号?我想“-g”选项将为我的程序和标准库带来调试信息,对吧?还是我必须为标准库的调试/源代码安装额外的包?我在 ubuntu16.04

非常感谢。

【问题讨论】:

    标签: ubuntu math gcc gdb symbols


    【解决方案1】:
    • cos 函数是在 libm 中实现的,而不是在 libc 中。你甚至链接了 -lm 吗?
    • 编译器优化掉常量表达式。没有理由在运行时计算 cos(0)。所以不需要包含 cos 函数,也不需要链接数学库。对 libm 的引用已从您的可执行文件中删除(您可以使用 readelf 或类似工具进行验证),因此 gdb 对 cos(或数学库中的任何其他函数)一无所知。
    • 正如 Tom Tromey 所解释的,一种可能的解决方法是禁用 gcc 的内置函数。在此之后,我可以从 gdb 调用 cos(例如:print cos(1.0))。

    【讨论】:

      【解决方案2】:

      尽管立即出现,但 gdb 的这一部分运行良好。所以我的第一直觉是我们处于某种 GIGO 情况——gdb 非常容易受到编译器和内核的敌对行为的影响——因此需要进行一些调查。

      你没有说你使用的是 C 还是 C++。

      在 C++ 中,我可以看到没有为 cos 发出调试信息,并且调用已完全优化。您可以通过运行nm 来检查这一点,并注意cos 不会显示为未定义的符号;或者只是注意到这个程序在没有-lm 的情况下可以正常链接。

      我对 C++ 的理论是,发生这种情况是因为在范围内有一个 constexpr 版本的 cos(我在预处理输出中看到它,但我没有尝试真正验证),因此 g++ 优化了整个通话。

      对于 C,默认情况下我会看到相同的内容。但是,我可以通过将 -fno-builtin-cos 传递给 gcc 来调用 cos。但是,哈哈,debuginfo里面还是没有!

      这对我来说似乎是一个 gcc 错误。通常,您不需要库的 debuginfo 来访问程序使用的库中的类型或函数。

      您还可以通过尝试打印函数本身来注意到发生了一些奇怪的事情:

      (gdb) p cos
      $1 = {<text gnu-indirect-function variable, no debug info>} 0x7ffff7aebc50 <cos>
      

      这是一个双重坏消息,因为“GNU 间接”函数是魔法生物,gdb 并不总是能正确理解。特别是我不认为它们可以从调试器中调用,即使安装了 debuginfo。

      事实上,我唯一能做的就是在程序中获取cos的地址,然后通过那个指针调用,比如:

      mumble *my_cos = &cos;
      ...
      (gdb) print my_cos(0.0)
      

      嗯,这并不完全正确。我也可以完成这项工作:

      (gdb) info func cos@plt
      All functions matching regular expression "cos@plt":
      
      Non-debugging symbols:
      0x0000000000400500  cos@plt
      (gdb) p ((double(*)(double))0x0000000000400500)(0.0)
      $6 = 1
      

      这避免了 GNU 间接的东西。但是,这很不愉快。

      【讨论】:

      • 谢谢,您的回复很中肯。您可以从 gdb print 中看到,我使用的是“x.c”文件,它不是 C++。好吧,起初我想知道为什么我可以在没有 -lm 的情况下编译它,现在我知道它正在被 gcc 的内置函数所取代。指定 -fno-builtin 时,需要 -lm。
      猜你喜欢
      • 2020-02-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-14
      • 2016-04-21
      • 2019-12-02
      • 2014-04-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多