gpt4 book ai didi

c++ - 调用dll函数时参数对象的成员变量的内存地址发生变化

转载 作者:可可西里 更新时间:2023-11-01 11:36:50 24 4
gpt4 key购买 nike

类 SomeClass {
//一些成员
MemberClass one_of_the_mem_;

我在 dll 中有一个函数 foo( SomeClass *object ),它是从 exe 调用的。

问题

one_of_the_mem_ 的地址在调度 dll 调用期间发生变化。

详细信息:

调用之前(从 exe):

             '&(this).one_of_the_mem_' - `0x00e913d0`

之后 - 在 dll 本身中:

             '&(this).one_of_the_mem_' - `0x00e913dc`

对象的地址保持不变。只有地址每次移动c的成员。

我需要一些关于如何解决这个问题的建议。

代码:

Exe 代码

stat = module->init ( this, object_a, &object_b, object_c, con_dir );

DLL 中的代码

Status_C ModuleClass( SomeClass *object, int index, Config *conf, const char* name)
{
_ASSERT(0); //DEBUGGING HOOK
...

更新 1:

我按照 Michael 的指示比较了成员的偏移量,它们在两种情况下都是相同的。

更新 2:

我找到了一种转储类布局的方法并注意到大小不同,但我必须弄清楚为什么会这样。

链接是我找到的转储类布局的问题。

更新 3: Class layout difference between exe and dll, but don't know why yet
最终更新:解决了问题,非常感谢 Michael Burr。

事实证明,其中一个构建使用的是 32 位时间,其中定义了 _USE_32BIT_TIME_T,而另一个使用的是 64 位时间。所以它为对象生成了不同的布局,附件是差异文件。

Diff in two classes due to sizeof `time_t'

最佳答案

您的 DLL 可能是使用不同的编译器选项集编译的(或者甚至可能是稍微不同的头文件),因此类布局不同。

例如,如果一个是使用调试标志构建的,而另一个不是,或者即使使用了不同的编译器版本。例如,不同编译器版本使用的库可能有细微差别,如果您的类包含库定义的类型,您可能会有不同的布局。

作为一个具体示例,Microsoft 的编译器迭代器和容器对发布/调试、_SECURE_SCL 开/关和 _HAS_ITERATOR_DEBUGGING 开/关设置敏感(至少在 VS 2008 之前 - VS 2010 可能已将其中一些更改为一定程度上)。参见 http://connect.microsoft.com/VisualStudio/feedback/details/352699/secure-scl-is-broken-in-release-builds了解一些细节。

这些类型的问题使得跨 DLL 边界使用 C++ 类比使用直接 C 接口(interface)更加脆弱。它们也可以出现在 C 结构中,但 C++ 库似乎更经常出现这些差异(我认为这是具有更丰富功能的本质)。

另一个不时发生的布局更改问题是在不同的编译中具有不同的结构打包选项。可以“隐藏”的一件事是 header 中经常使用 pragma 来将结构打包设置为某个值,有时您可能会遇到 header 执行此操作而没有将其更改回默认值(或更准确地说是以前的设置).如果您有这样的 header ,很容易将它包含在一个模块的构建中,而不是另一个模块。

关于c++ - 调用dll函数时参数对象的成员变量的内存地址发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9472616/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com