【问题标题】:Optimization makes function return immediately instead of executing优化使函数立即返回而不是执行
【发布时间】:2011-10-25 18:00:42
【问题描述】:

我正在开发 VS 2010 express 并尝试做一些文件读取和解析工作

我的功能是这样的......(我放弃了无聊的部分)

void SomeClass::SomeFunc(char *ALName, std::map<...> *chromList, std::map<...> *chromLine)
{
    ifstream file;
    char tmpBuff[500];
    char tmpBuff2[500];
    char fileName[350];
    char tmp[350];
    char *pch;
    char *pch2;

    .....

    file.open(fileName);

    while ( file.getline( tmpBuff, 500 ) ) 
    {
        ....
        if ( some_condition == 0 )
        {
          pch2 = strtok( NULL, "," );
          pch = strtok( NULL, "," );
          (*chromList)[pch2] = do_some_work( atoi(pch), tmpBuff2 );
          strcpy( tmp, get_chrom_line( tmpBuff2 ) );
          (*chromLine)[pch2] = tmp;
        }
    }

    file.close();

 }

当我将优化设置为最大速度更改为发布时,将跳过此功能。 调试器进入函数后立即返回。

当我在调试设置或优化标志设置为禁用的情况下运行时,该功能运行良好。

这可能是什么原因? 我可以放置一个预处理器定义来强制这个函数“无优化”,而其余的代码得到优化

谢谢!! 伊丹

【问题讨论】:

  • 我认为无聊的部分可能很重要。由于您正在从文件中读取,编译器必须承担副作用并且可能不会优化读取。
  • 启用优化的调试很棘手,因为执行的代码不一定在相同的位置/顺序。此外,您不一定要依赖显示真实值的手表值。
  • -->1 无聊的部分主要包含文件路径连接和简单的 strtok 和 strcmp 调用。 -->2 我没有尝试调试发布代码,但我可以看到它什么也没做。
  • 也许编译器认为 some_condition 永远不会等于 0,所以它省略了该部分。我们可以看看“some_condition”部分吗?
  • 可能的问题:“some_condition”以某种方式设法被扣除为始终非零。或者可能一些缓冲区溢出,并覆盖您的指针。结果,您将元素添加到地图中,而不是您认为自己添加的那些地图。该错误也可能在“do_some_work”函数中,它会破坏您的堆栈。

标签: c++ c visual-studio-2010 optimization release


【解决方案1】:

您永远不应该尝试调试优化的代码。它显示的行号很少会与实际执行的内容匹配,并且忘记读取局部变量。这就是为什么有“调试”和“发布”模式的原因。

但是,如果你真的想,try this 让 Visual Studio 不优化该功能。您也可以将该函数放在单独的源文件中并在调试模式下编译它。

【讨论】:

  • 感谢您的回答。我不是在尝试调试“发布”代码,但这个函数的输出很奇怪。代码在发布模式下编译(优化开启),但这个函数没有被执行。无论我是调试它还是运行 output.exe
  • 嗯,这很有趣。你怎么知道它没有被执行?我想你可以把那个 pragma 留在那里,这样函数就永远不会得到优化。
  • chromList 和 chromLine 映射保持空白...我会尝试用 pragma 包装它谢谢!
【解决方案2】:

您确定该函数实际上被跳过并且调试器不只是让它看起来被跳过了吗?

如果它真的没有被执行,那么几乎可以肯定你有未定义的行为,在未优化时恰好按你想要的方式工作,并且编译器(可能是正确的)在优化模式下将其优化为非工作代码。

也就是说,我看到了一些有问题的项目:您使用 NULL 调用 strtok(除了 - 在 C++/C++11 中更喜欢 0nullptr)而没有使用有效指针调用它。你知道strtok 具有破坏性吗?

然后你使用一个字符指针来索引一个数组,或者大概(希望?)调用一个带有char* 参数的重载operator[] 函数。

由于这是 C++,如果您删除所有 C 样式的解析并使用 stringfind/find_first_of/etc 执行此操作,您的代码将更干净、更安全并且可能更容易调试,具体取决于您的需要。

【讨论】:

  • 我将更改 strtok 操作。它是为测试而建造的,并保持这种状态。 operator[] 不是问题,映射键是 std::string,因此进行了隐式转换。
猜你喜欢
  • 1970-01-01
  • 2020-10-26
  • 2023-02-24
  • 1970-01-01
  • 2015-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多