无法在某个 C 文件中看到全局变量,值似乎重置



我有一个非常令人沮丧的错误,团队中的其他人无法重现。我尝试清理项目,擦除目录,从存储库中提取,重建,甚至在VS 2013中进行测试。

背景:a.c,b.c,c.c和b.inc都被编译成一个DLL(假设它们是外部的)。 首先从托管代码调用setfoo()。目前为止,一切都好。

后来,testfoo()被召唤。全局变量很好,没有问题。然后调用testfoo2()。这就是事情变得有趣的地方。我有带有foo's地址的内存调试器,它将在内存中读取 4。但是,如果将鼠标悬停在 Visual Studio 中的代码上,它将返回 0!。此外,它将输出 0。有许多全局变量(包括FILE句柄,它们被重置为零(导致讨厌的 ASSERT 故障),仅在 c.c 中,但在使用调试器检查时很好)。还有许多其他 x.c 模块包含没有问题。

好的,现在再次调用testfoo()。在BC世界一切都很好。可怕的是,问题只发生在我的工作站上!关于如何调试它的任何线索?

这是我的记忆,我相信代码非常接近这个骨架:

B.Inc

int foo;

交流电

#include <b.inc>
void setfoo(){
    foo = 4;
}

不列颠哥伦比亚省

#include <b.inc>
void testfoo(){
    printf(foo); //works
}

C.C

#include <b.inc>
void testfoo2(){
    printf(foo); //foo is now 0
}

补充:这是一个非常复杂的遗留代码(想想70年代),在一个非常大的公司中,没有太多可以改变的。如果我们开始添加 extern,有数千个变量会受到影响。另外,我尝试对一个变量进行 extern,但它仍然与该文件有问题。

我漏掉了一个花絮。'testfoo2()' 在托管线程中启动。同样,这似乎与我的机器有关,可能是Visual Studio中的一些设置,在这一点上,我们只想重新映像盒子。

你需要声明为 extern:

extern int foo;

然后在一个(并且只有一个)源文件中定义它:

int foo;

这样,一个源文件中只有一个符号,并且包括标头在内的所有其他源都知道链接到它。 如果省略extern则每个源文件都认为它有自己的本地私有副本foo

那么哪个文件应该定义它呢? 最相关的一个。 我会说a.c,因为这提供了在foo上运行的功能。 我认为该文件是"所有者"。 但是,这有点令人困惑,因为您在b.inc中声明它,暗示b.c是所有者。

试试这个。

B.Inc

extern int foo;

交流电

#include <b.inc>
int foo;
void setfoo(){
    foo = 4;
}

我在另一个线程中发布了这个,但我会在这里复制答案。这是一个非常微妙的错误,可能会为您节省几个小时:

好的,这是发生的事情:(以防您将来遇到这种情况)

1)在以前的构建中,有人将所有 C# Extern dll 调用拆分为两个文件。(我没有被告知)

2)他们创建了一个后期构建过程,将 dll 复制到另一个目录(请参阅其去向)。

3)涉及一个用户设置文件,该文件不在存储库中,但在代码中具有默认值。

4)其中一个 extern DLL 函数保留了我原来的默认值(在 filea.cs 中),但新的默认值 (fileb.cs) 指向构建后的位置。

我所知,没有真正的方法可以在运行时反映 dll 的路径......

所以,当我使用 dll 副本输入函数时,当然没有全局变量,因为它是 dll 的新鲜副本。这是预期行为。

内存调试器是正确的,因为另一个 dll 在内存中的某个地方保存正确的变量。

将来如何防止这种情况发生?当VS加载同一dll的副本时,它似乎被欺骗了。

相关内容

  • 没有找到相关文章

最新更新