如何防止编译器优化对从未使用过的变量的加载

时间:2013-09-06 10:52:11

标签: c++ visual-c++ compiler-optimization dead-code seh

说明: 我试图快速破解修复旧代码并使用__try MSVC扩展来检查某些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上进行pragma优化的文档很糟糕,也就是说“”是否禁用该函数的所有优化还不清楚。

3 个答案:

答案 0 :(得分:10)

首先,这是一个pretty bad idea,所以你可能想要考虑整个设计。但如果你被迫坚持下去,那就像:

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,因此无法对其进行优化。

答案 1 :(得分:4)

Windows API

BOOL WINAPI IsBadReadPtr(_In_ const VOID *lp,_In_ UINT_PTR ucb);
BOOL WINAPI IsBadWritePtr(_In_ LPVOID lp, _In_ UINT_PTR ucb);

您需要阅读备注部分,但您的情况可能很简单,这些功能可能就足够了。无论备注部分在尝试自己处理不安全指针时提供了一些有用的建议。

答案 2 :(得分:0)

从SO的回答到类似的问题似乎是:

  • 编译器依赖
  • 非平凡

我发现的最佳信息来源是问题/答案:

Check if a pointer points to allocated memory on the heap

对我来说最合理的是:

  1. 静态分析(valgrind),调试,重构
  2. 为编译器使用一些hack
  3. 检查该答案中公布的商业解决方案