好吧,所以这听起来像是一个愚蠢的问题,但我被困住了:我在lldb调试会话期间读取变量的值时遇到了麻烦(gdb工作正常) .
我发现其他人遇到的错误消息比我自己的帖子,但不同的是我甚至无法弄清楚如何打印出最简单形式的变量的值 .
为了更好地表达我的问题,我将在这里考虑一个非常简单的例子 . 我们有一个文件“main.c”,其中包含以下代码:
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int a = 1;
int b = 2;
int c = 0;
c = a + b;
c = c*b;
printf("c = %d\n", c);
return 0;
}
我用它编译它:
user@machine ~ $ gcc -g main.c
生成名为“a.out”的二进制文件
我然后ivoque lldb:
user@machine ~ $ lldb-3.4 ./a.out
我想在第9行停下来读取c的值 . 因此,我首先添加一个断点:
(lldb) breakpoint set -f main.c -l 9
然后我运行代码:
(lldb) run
到目前为止,每件事都按预期进行 . 现在是棘手的部分:我想读取变量c的值 . 因此,我写道:
(lldb) print c
而lldb回报我:
error: use of undeclared identifier 'c'
error: 1 errors parsing expression
当然 :
(lldb) expression c
返回完全相同的错误消息 .
有什么我错过的吗?任何帮助将非常感谢 .
我的设置:
-
lldb:"lldb version 3.4 ( revision )"(包v . :"3.4~svn183914-1ubuntu1")
-
gcc:"gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1"(包装版:"4.8.1-2ubuntu3")
-
(我的存储库是linux mint 16默认提供的存储库)
@Sean Perry回答后的更多信息:
1:似乎附加选项-O0不会改变调试器的行为 .
2:我还尝试使用以下虚拟代码而不是之前的代码
#include <stdlib.h>
#include <stdio.h>
int main(void) {
long a = 1;
long b = 2;
long c = 0;
c = a + b;
c += (long) &c;
printf("c = %ld\n", c);
return 0;
}
我不确定@Sean Perry是什么意思“使用指针”,但我认为它必须阻止代码优化,因为变量c的地址(或多或少)随机地改变二进制文件的每次运行 .
3:最后,我发现了一些有趣的东西:
-
用gcc编译[-g -O0]然后用gdb调试:工作
使用gcc [-g -O0]进行 -
编译然后使用lldb进行调试:不起作用
-
使用clang [-g -O0]进行编译然后使用gdb进行调试:有效
-
使用clang [-g -O0]进行编译然后使用lldb进行调试:有效
edit1:回复@SeanPerry edit2:区分软件版本和软件包版本
3 回答
使用
gcc 4.8.1
和lldb-3.4
时,这似乎是一个特定的问题使用
gcc-4.8.2
和gcc-4.7.3
工作正常 .调查行为的最佳方法是're seeing is to look at the debug info. On a Mac OS X system, you'在
.dSYM
包或.o
文件上运行dwarfdump(如果您没有创建dSYM) . 调试信息具有从编译器到调试器的关于在何处查找变量的指令 .在实时进程中,使用lldb,您可以让lldb显示所有局部变量的存储位置(以DWARF位置表达式语言表示),其中包含
image lookup -v -a $pc
(或简称im loo -va $pc
) .如果有's a program where gdb can' t打印变量并且lldb在同一个pc地址不能,那听起来好像它可能是一个lldb bug . 调试信息是最终的事实(就调试器而言)关于存储变量的位置以及它们的长度"live" . 在优化的代码中,它们可能适用于函数的非常短的部分 .
从黑客的角度来看,真正的真相来源是阅读汇编代码 . 通常情况下,在优化过程中,编译器不会跟踪变量的位置 - 它可能会说某个变量在给定的pc地址不可用,但如果你仔细阅读了程序集,你可能会发现仍然保存在堆栈上的最后一个值的副本等 .
这段代码非常简单我敢打赌llvm完全删除了这些变量 . 尝试编译并禁用优化(-O0)并查看是否有帮助 . 除此之外,使用指针或做一些更复杂的事情,因此编译器不会删除数学并用预先计算的值替换它 .