如何防止编译器优化对从未使用的变量的加载
How to prevent compiler from optimizing a load to variable that is never used
简介:我试图快速破解旧代码并使用 MSVC 扩展__try检查某些 ptr 是否指向一些合法内存,或者 *ptr 是否会导致内存违规(如果是这样,我会放弃处理此 ptr)。所以我写了这样的东西:
bool checkIsPtrPointingToValidAddress(const void *ptr)
{
__try
{
auto cpy = *((int*)ptr); // force mem access...
if ( (cpy ==42) && ((rand()+rand()+rand()+rand()+ rand()) == 1))
{
FILE* pFile = fopen ("tempdata.dat","w"); //... by unlikely but possible action
fputs (" ",pFile);
fclose (pFile);
}
return true;
}
__except(1)
{
return false;
}
}
问题是我强制访问mem的解决方案似乎很奇怪,丑陋,作为奖励,我不确定它是否正确。另外请不要我无法禁用整个项目的优化,因此这不是一个选项。MSDN上的杂注优化文档很糟糕,也就是说,不清楚"是否禁用了对函数的所有优化。
首先,这是一个非常糟糕的主意,所以你可能想考虑整个设计。但是,如果您被迫坚持下去,那么例如:
volatile auto copy1 = *((char*)ptr); // using int* here could lead to aliasing violations, so better char in the general case..
volatile auto copy1 = *((char*)ptr);
if (copy1 != copy2)
throw std::exception("Cannot happen, but compiler cannot know this");
当然应该做这个伎俩。编译器无法消除读取或假设它们是相同的,因此必须执行代码。另一方面,假设没有线程问题或其他有趣的场景,我们知道两个读取将是相同的,因此不会导致抛出异常。
添加
根据该标准的规则,任何对易失性对象的读取或写入都构成可观察的行为(也称为副作用),因此即使满足以下条件也足够了:
volatile auto copy = *((char*)ptr);
这包括写入易失性对象copy
,因此无法将其优化。
Windows API 有
BOOL WINAPI IsBadReadPtr(_In_ const VOID *lp,_In_ UINT_PTR ucb);
BOOL WINAPI IsBadWritePtr(_In_ LPVOID lp, _In_ UINT_PTR ucb);
您需要阅读备注部分,但您的情况可能很简单,这些功能可能就足够了。 无论如何,备注部分在尝试自己处理不安全的指针时都会提供一些有用的建议。
从SO对类似问题的回答来看,似乎是:
- 依赖于编译器
- 非平凡
我找到的最佳信息来源是这里的问题/答案:
检查指针是否指向堆上分配的内存
对我来说最合理的似乎是:
- 静态分析(Valgrind),调试,重构
- 为您的编译器使用一些技巧
- 检查该答案中宣传的商业解决方案
相关文章:
- 使用typeid警告未使用的变量
- 未使用的C++未优化的静态成员函数/变量
- C++未使用的变量警告,即使我在函数结束时返回它
- 如何使 Visual Studio 2010 警告未使用的变量
- C 20合同和未使用的变量
- 提升::序列化警告未使用的变量file_version
- 未使用的变量禁止打印?
- GCC和Clang不警告未使用的异常变量
- 避免在 openmp 并行块中使用预编译器语句出现未使用的变量警告
- 抑制警告:未使用的变量
- 错误:非静态数据成员的使用无效,在此范围内未声明变量
- 如何使用非平凡析构函数防止未使用的变量警告
- 为什么这个未使用的变量没有优化掉?
- 为什么msvc编译器在显式调用析构函数时会发出未使用的变量
- 警告:变量已设置,但未使用
- 检测函数范围之外的未使用变量
- 如何禁止显示有关C++中未使用变量的警告
- C++未使用变量的异常
- 为什么在c++函数中使用void(未使用)(和类似的)而不是没有名称的参数来消除未使用变量的警告
- 如何在Eclipse中禁用未使用变量警告?