【发布时间】:2015-04-29 20:14:57
【问题描述】:
我有一个问题,当我尝试访问某个文件中的某个类的成员时,它没有获得该成员的实际值。但是当我尝试在其他地方访问它时,我会这样做。
文件 A:
find_func_wrapper ( Func_Container * rules, char * func_name ) {
ulong count = rules->function_count;
cout << "A count: " << count << endl;
B::find_func( rules, func_name );
}
main () {
Func_Container *rules = get_rules();
find_func_wrapper( rules, func_name );
}
文件 B:
B::find_func ( Func_Container * rules, char * func_name ) {
ulong count = rules->function_count;
cout << "B count: " << count << endl;
}
当我运行它时,我得到:
A count: 2
B count: 0
当计数成员设置为 2。使用 gdb 单步执行代码时,在 A 和 B 中,当我使用 print rules->function_count 时,我得到 2。
反汇编代码,在 A find_func_wrapper 中。
1885 ulong count = rules->function_count;
=> 0x0000000006004be5 <+294>: mov -0xa8(%rbp),%rax
0x0000000006004bec <+301>: mov 0x60a8(%rax),%rax
0x0000000006004bf3 <+308>: mov %rax,-0x38(%rbp)
还有print &rules->function_count = 0x11684158 和print rules = 0x1167e0b0
而在 B::find_func
2652 ulong count = rules->function_count;
0x00000000062494a1 <+75>: mov -0x4f8(%rbp),%rax
0x00000000062494a8 <+82>: mov 0x60e8(%rax),%rax
0x00000000062494af <+89>: mov %rax,-0x50(%rbp)
打印规则的地址和 ->function_count 返回与预期相同的地址。对我来说,罪魁祸首似乎在第二条 mov 指令中,其中 B 中使用的偏移量 0x60e8 不正确。为什么会发生这种情况?
get_rules() 返回一个指向全局对象的指针,该对象在之前初始化并一直保留到程序结束。
这是用 gcc 4.4.7 编译的。该项目非常庞大。此外,这只发生在调试版本中,发布版本或非优化版本似乎没有这个问题。
Sizeof in find_func_wrapper: 24968
Offset: 3093
Sizeof in B::find_func: 25032
Offset: 3101
由((&rules->function_count) - rules)计算的偏移量
【问题讨论】:
-
这听起来与对齐有关。通常,当您将类存储到文件时,您会在标题之前指定对齐方式。在 Visual Studio 中类似于 #pragma pack(1)
-
确保两个 TU 共享相同的
Func_Container定义并进行清理和重建。 Visual Studio 有时会搞砸并忘记重新编译目标文件。 -
你确定这两个文件是用相同的标志编译的吗?这听起来像 func_container 可能有可选的 ifdef 字段。在两个函数中打印 sizeof(func_container)。
-
在重新安排了一些事情之后,我发现这似乎是因为 _GLIBCXX_DEBUG。 B 中包含的第一个标头定义了这一点。如果我包含 Func_Container 的标题,它可以正常工作。我没有立即在 Func_Container 的定义中看到 #ifdef 依赖于该值的任何内容,但我不知道它会导致编译器做什么。
-
请将您的最后一条评论添加为更详细的答案,并转发给下一个人。
标签: c++ gcc assembly compilation