SF.*_*SF. 5 c++ gcc compiler-optimization
我程序中的一个命名空间分布在两个文件之间.一个提供"引擎",另一个使用"引擎"来执行各种命令.所有初始化都在"引擎"端执行,包括从安装库获取的缓存参数.
所以,有engine.cpp:
#include <stdio.h>
#include "ns.h"
namespace MyNS
{
unsigned char variable = 0;
void init()
{
variable = 5;
printf("Init: var = %d\n",variable);
}
void handler()
{
// printf("Handler: var = %d\n",variable);
}
}
Run Code Online (Sandbox Code Playgroud)
变量永远不会被再次使用,engine.cpp但它被广泛使用commands.cpp.
#include <stdio.h>
#include "ns.h"
namespace MyNS
{
extern unsigned char variable;
void command()
{
printf("Command: var = %d\n",variable);
}
}
Run Code Online (Sandbox Code Playgroud)
编译和链接后,我得到:
Init:var = 5
命令:var = 1
现在,如果我取消注释printf(),handler()我得到:
引擎:var = 5
命令:var = 5
处理程序:var = 5
什么是"正确"的方式迫使GCC不以这样的方式优化它以便extern从其他文件访问它将获取正确的值?优选地,不降低-O其余应用的水平?
(完整性案例,main.h和ns.h:)
#include "ns.h"
int main(int argc, char** argv)
{
MyNS::init();
MyNS::command();
MyNS::handler();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
namespace MyNS
{
void init();
void command();
void handler();
}
Run Code Online (Sandbox Code Playgroud)
这种最小化的测试用例没有表现出这种特殊行为; 似乎人们需要在更复杂的环境中发生这种情况......
呃...解决方案非常简单。
我交换了变量的声明和定义的位置。
engine.cpp:
extern unsigned char variable;
command.cpp:
unsigned char variable = 0;
这样,编译器在编译时就不会怀疑该变量是否存在,commands并且engine必须到达现有实例,而不能只是当场创建一个临时变量。
编辑:现在我发现了另一个特点。该值根据写入位置而变化。有问题的代码部分是:
1: varso = SharedObject::Instance()->varso;
2: memset(det_map,0,sizeof(det_map));
3: memset(gr_map,0xFF,sizeof(gr_map));
4: memset(gr_ped,false,sizeof(gr_ped));
5: memset(&stan,0,sizeof(stan));
6: stan.SOTUstage = 1;
7: PR_SOTU = varso->NrPSOTU;
Run Code Online (Sandbox Code Playgroud)
该变量出现在使用 memset 初始化多个数组的位置附近。有问题的变量是PR_SOTU(大写字母是从它仍然是宏时继承的,并且由于它与在非常相似的上下文中运行的其他几个宏一起运行,因此它可能会保持这种状态)。
如果将作业从第 7 行移至第 1、2 或 3 行之后,它将收到正确的值5。放置在第 4 行之后,它会获取值18。以下任何内容,其值为1。我将变量的定义移动到另一个位置(它是所有名称空间全局列表中的最后一个,现在是第一个),以排除在该特定内存位置写入某些内容的可能性,但行为仍然存在。