类别成员偏移地址不正确

Incorrect Class Member Offset Address

本文关键字:地址 不正确 成员      更新时间:2023-10-16

我遇到一个问题,当我试图访问某个文件中某个类的成员时,它无法获得该成员的实际值。但当我试图在其他地方访问它时,我会这样做。

文件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。

在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 = 0x11684158print 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)

打印rules和->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)计算的偏移

我能够通过重新排列头包含来缩小问题的来源。在将#include "Func_Container.h"放在文件B中的其他include之前之后,我发现容器的大小是正确的。我继续移动Func_Container之前的其他标头,直到我发现是哪一个导致了问题。我发现有问题的标头定义了_GLIBCXX_DEBUG标志。这导致某些std类型中的额外调试成员改变了它们的大小,所以当我在以后的成员中加载Func_Container的定义时,由于较大的类型,地址发生了变化。

此邮件列表中提供了该问题的示例:https://gcc.gnu.org/ml/libstdc++/2012-10/msg00077.html