具有 GCC 优化的 C++ 代码导致核心在字符串上具有无效的 free()

Posted

技术标签:

【中文标题】具有 GCC 优化的 C++ 代码导致核心在字符串上具有无效的 free()【英文标题】:C++ code with GCC optimisation causes core with invalid free() on strings 【发布时间】:2013-02-12 17:17:43 【问题描述】:

我有使用 gcc (4.1.2) 和 -O2 构建的 C++ 代码。

当这段代码在没有优化的情况下编译和运行时,程序执行没有任何问题。

当使用 O1/O2/O3 编译时,代码将崩溃并出现一个 valgrind 指示无效的空闲。 这已经缩小到函数内部的字符串变量。

代码将读入文件,并迭代内容。 我把所有的处理代码都去掉了,下面的代码sn -p导致核心...

int MyParser::iParseConfig(Config &inConfig)

    bool keepGoing = true;

    while(keepGoing)
    
        string valueKey = "";
        keepGoing = false;
    
    return 0;

当它在未优化的情况下运行时,它可以正常工作。 当我构建并运行此优化后,它将无法正常工作。

看来是 GCC 优化字符串类的方式有问题。

有什么办法可以规避这个问题吗?

【问题讨论】:

你检查了你所有的free()delete 电话吗? 我觉得没问题。不过,缺少的 else 子句似乎很可疑。 崩溃时i的值是多少?如果超过 99,则您的 charIndex 数组存在缓冲区溢出问题。 可以i > 99 ??有关将 int 附加到 std::string 的替代方法,请参阅 ***.com/questions/10516196/… 您能否在一个小的独立代码示例中重现此行为,人们可以尝试在他们自己的系统上进行分析? 【参考方案1】:

如果您溢出 charIndex,(当 i 高于 99 时)谁知道您的程序状态是什么...您声明的存储空间不是很大(2 个字符和一个 null)。

【讨论】:

【参考方案2】:

我无法解释为什么这段代码在使用优化编译时会为您崩溃,也许i 超过 2 位并且您有缓冲区溢出,也许这是不同的东西,但无论如何我会更改代码:

    sprintf(charIndex, "%d", i++);
    string valueKey = "";
    valueKey.append("Value").append(charIndex);
    string value = inConfig.sFindField(valueKey);

像这样:

    stringstream ss;
    ss << "Value" << i++;
    string value(ss.str());

它更像 C++ 并且应该可以工作。试试看。

如果你好奇这是否真的是缓冲区溢出情况,请插入以下行:

    assert(i < 99);

在致电printf 之前。或者使用snprintf:

    snprintf(charIndex, sizeof(charIndex), "%d", i++);

或者让你的缓冲区更大。

【讨论】:

一个猜测:优化后,charIndex 被压缩成三个字节。未优化时,charIndex 有一些填充。另一种可能性是优化器正在移动东西,因此溢出的项目正在改变。【参考方案3】:

这是一个错误包含头文件的问题 - 在包含列表中存在重复包含的 MyParser.h 文件。 这在 GCC 优化级别中围绕字符串优化引起了一些奇怪的情况。

【讨论】:

以上是关于具有 GCC 优化的 C++ 代码导致核心在字符串上具有无效的 free()的主要内容,如果未能解决你的问题,请参考以下文章

GCC 优化在运行时导致“未定义的符号”

gcc,c++:静态字符串成员变量导致堆损坏/分段错误

由于 std::pair 导致的 GCC (MoSync) 中的 C++ 构建错误

从 GCC 获取优化的源代码

可以跨 C 和 C++ 方法优化 gcc 或 clang 的 LTO

线程(c++ 中的并行计算)是不是与优化级别(gcc)不兼容?