_处理匿名命名空间里的变量时进入硬件中断错误
最近在初次使用匿名空间时出现一个很离谱的错误,我先简单描述一下情形:在匿名命名空间里有一个变量(全局),在命名空间外,有一个内联函数操作该空间内的变量。
如果开优化,那么程序就会进入硬件错误中断;如果不开,那么函数仿佛未执行,变量没有被置零。如果把变量声明放在hpp文件的匿名空间外里,并且变量定义放在cpp里就没有问题了。
后来才发现,匿名命名空间里的东西只能在该编译单元起作用。每个翻译(编译)单元中的全局变量都是独立的,因此在不同文件中调用这个内联函数只会影响各自文件中的全局变量,而不会影响其他文件中的全局变量。
如果在 .hpp 文件中匿名命名空间外部定义一个 static 变量,并在同一个文件中定义一个静态内联函数来操作这个变量,然后在其他文件中调用这个内联函数,这种做法仍然会导致每个翻译单元有一个独立的变量副本。这是因为 static 关键字在类外变量声明时也会赋予该变量内部链接属性,使其在每个翻译单元中都有一个独立的副本。
总而言之,尽量不要在匿名命名空间里定义变量,除非你明确该变量只在该翻译单元内使用,且不会以函数等方式间接被修改。同样的,在头文件里可以声明但不要定义静态变量,否则生成的只会是副本。
之所以使用匿名空间,是因为最近开发的需求中不希望变量或者一些函数外露,但又希望简单一点不使用类,同时接口是模板函数,那么这时候就可以使用匿名命名空间,也算某种意义上的“闭包”。当然对于到处漏风的宏定义除了#undef就没有更好的方法了,匿名命名空间并不属于预处理阶段,所以管不了宏定义。
失败的调试片段:
开始时我从汇编查找,最后只是加深了对代码优化的理解,但并没有解决问题
可以右键调试框,打开寄存器的始终显示,这样就可以查看CPU寄存器了。
打开汇编一看,程序出错了,被优化得很厉害
接下来把这段代码关闭优化,我们可以看到汇编正常多了
#pragma GCC push_options #pragma GCC optimize ("O0") /***xxxxx***/ #pragma GCC pop_options
只不过一级优化后还是暴毙了
现在虽没有被卡死,但函数仿佛没有执行(事后回想起来,这应该是初见端倪)
后面还是由于对匿名命名空间不怎么熟,所以就突然想到会不会是匿名命名空间对变量有什么特殊的处理,于是问了一下AI这个场景,让它预测一下可能出现的情况。答案是,它还是有实力的