考虑以下4个文件:
[core.h]
#pragma once static int MY_MARK = -1;[count.h]
#pragma once #include "core.h" #include <stdarg.h> #define Count(...) CountImpl(&MY_MARK, __VA_ARGS__, &MY_MARK) int CountImpl(void*, ...);[count.c]
#include "count.h" int CountImpl(void* dummy, ...) { int count = 0; va_list lst; va_start(lst, dummy); for(;;) { void* ptr = va_arg(lst, void *); if(ptr == &MY_MARK) {break;} ++count; } va_end(lst); return count; }[WeirdProblem.c]
#include <tchar.h> #include "count.h" int _tmain(int argc, wchar_t* argv[], wchar_t* envp[]) { int a = 1; int b = 2; int c = 3; int d = Count(&a, &b, &c); return 0; }我正在使用Microsoft Visual Studio Community 2013。 当运行上面的代码时,我希望'd'变量的值为3.问题是执行永远不会从循环中断,因为它不会比较'ptr'和'&MY_MARK'是相等的。 (最终它会在尝试读取受保护的内存或其他任何内容时抛出错误。) 实际上,我在Watch窗口中看到两个不同的地址:
(int*)ptr 0x000000013f8d9004 {WeirdProblemTest.exe!int MY_MARK} {-1} int * &MY_MARK 0x000000013f8d9000 {WeirdProblemTest.exe!int MY_MARK} {-1} int *我知道我可以使用'dummy'变量解决问题而不是引用'&MY_MARK',但这不是重点。 我真的需要了解发生了什么,因为同样的问题发生在我的代码的不同部分,并且那里没有这么好的解决方法。
很抱歉很长的帖子,但我发现没办法让它缩短。
Take into consideration the following 4 files:
[core.h]
#pragma once static int MY_MARK = -1;[count.h]
#pragma once #include "core.h" #include <stdarg.h> #define Count(...) CountImpl(&MY_MARK, __VA_ARGS__, &MY_MARK) int CountImpl(void*, ...);[count.c]
#include "count.h" int CountImpl(void* dummy, ...) { int count = 0; va_list lst; va_start(lst, dummy); for(;;) { void* ptr = va_arg(lst, void *); if(ptr == &MY_MARK) {break;} ++count; } va_end(lst); return count; }[WeirdProblem.c]
#include <tchar.h> #include "count.h" int _tmain(int argc, wchar_t* argv[], wchar_t* envp[]) { int a = 1; int b = 2; int c = 3; int d = Count(&a, &b, &c); return 0; }I'm using Microsoft Visual Studio Community 2013. When running the code above, I would expect the 'd' variable to have a value of 3. The problem is that the execution never breaks from the loop, as it does not compare 'ptr' and '&MY_MARK' to be equal. (Eventually it throws an error trying to read protected memory or whatever.) Actually, I see two different addresses in the Watch window:
(int*)ptr 0x000000013f8d9004 {WeirdProblemTest.exe!int MY_MARK} {-1} int * &MY_MARK 0x000000013f8d9000 {WeirdProblemTest.exe!int MY_MARK} {-1} int *I know I could workaround the issue using the 'dummy' variable instead of referring to '&MY_MARK', but that's not the point. I really need to understand what is going on, because the same problem is happening in different parts of my code and in there there's not such a nice workaround for them.
Sorry for the long post, but I found no way to keep it shorter.
最满意答案
您已将.h文件中的变量声明并定义为static ,这意味着#includes标头的每个文件都将获得它们自己的变量私有副本。
您需要将core.h拆分为core.h和core.c如下所示:
core.h:
#pragma once extern int MY_MARK;core.c:
#include "core.h" int MY_MARK = -1;所有其他文件应该#include "core.h" ,编译和链接时你应该在core.c链接
You have both declared and defined the variable in the .h file as static which means that every file that #includes the header will get their own private copy of the variable.
You need to split core.h into core.h and core.c looking something like:
core.h:
#pragma once extern int MY_MARK;core.c:
#include "core.h" int MY_MARK = -1;All other files should #include "core.h", and when compiling and linking you should link in core.c
更多推荐
发布评论