C++ 程序在执行 std::string 分配时总是崩溃

Posted

技术标签:

【中文标题】C++ 程序在执行 std::string 分配时总是崩溃【英文标题】:C++ Program Always Crashes While doing a std::string assign 【发布时间】:2011-01-19 05:04:42 【问题描述】:

我一直在尝试调试我的应用程序崩溃(即断言 * 检测到 glibc * free(): invalid pointer: 0x000000000070f0c0 ***) 而我正在尝试对字符串进行简单的分配。请注意,我正在使用 gcc 4.2.4 的 linux 系统上编译,优化级别设置为 -O2。使用 -O0,应用程序不再崩溃。

例如

std::string abc;

abc = "testString";

但如果我按如下方式更改代码,它就不再崩溃了

std::string abc("testString");

所以我又挠了挠头!但有趣的模式是,崩溃在应用程序中稍后移动,AGAIN 在另一个字符串处。我发现应用程序在字符串分配上不断崩溃,这很奇怪。典型的崩溃回溯如下所示:

#0  0x00007f2c2663bfb5 in raise () from /lib64/libc.so.6
(gdb) bt
#0  0x00007f2c2663bfb5 in raise () from /lib64/libc.so.6
#1  0x00007f2c2663dbc3 in abort () from /lib64/libc.so.6
#2  0x00000000004d8cb7 in people_streamingserver_sighandler (signum=6) at src/peoplestreamingserver.cpp:487
#3  <signal handler called>
#4  0x00007f2c2663bfb5 in raise () from /lib64/libc.so.6
#5  0x00007f2c2663dbc3 in abort () from /lib64/libc.so.6
#6  0x00007f2c26680ce0 in ?? () from /lib64/libc.so.6
#7  0x00007f2c270ca7a0 in std::string::assign (this=0x7f2c21bc8d20, __str=<value optimized out>)
    at /home/bbazso/ThirdParty/sources/gcc-4.2.4/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:238
#8  0x00007f2c21bd874a in PEOPLESProtocol::GetStreamName (this=<value optimized out>,
    pRawPath=0x2342fd8 "rtmp://127.0.0.1/mp4:pop.mp4", lStreamName=@0x7f2c21bc8d20)
    at /opt/trx-HEAD/gcc/4.2.4/lib/gcc/x86_64-pc-linux-gnu/4.2.4/../../../../include/c++/4.2.4/bits/basic_string.h:491
#9  0x00007f2c21bd9daa in PEOPLESProtocol::SignalProtocolCreated (pProtocol=0x233a4e0, customParameters=@0x7f2c21bc8de0)
    at peoplestreamer/src/peoplesprotocol.cpp:240

这确实是一种奇怪的行为,因此我开始在我的应用程序中进一步查看是否存在某种可能导致这种奇怪行为的内存损坏(堆或堆栈)错误。我什至检查了 ptr 损坏并空手而归。除了对代码进行视觉检查之外,我还尝试了以下工具:

Valgrind 同时使用 memcheck 和 exp-ptrcheck 电围栏 libsafe 我在 gcc 中使用 -fstack-protector-all 编译 我尝试将 MALLOC_CHECK_ 设置为 2 我通过 lint 检查和 cppcheck(检查错误)运行我的代码 我使用 gdb 逐步完成了代码

所以我尝试了很多东西,但仍然空手而归。所以我想知道它是否可能是链接器问题或某种可能导致此问题的库问题。 std::string 是否存在任何已知问题,使得 make 容易在 -O2 中崩溃,或者它可能与优化级别无关?但到目前为止,我在问题中看到的唯一模式是它似乎总是在字符串上崩溃,所以我想知道是否有人知道我导致这种行为的任何问题。

非常感谢!

【问题讨论】:

而 valgrind 什么也没说?您能否详细介绍 libc、libstdc++、内核和 Linux 发行版? 你能显示这个:VANSProtocol::GetStreamName 和这个:VANSProtocol::SignalProtocolCreated 吗? 你能试试更新的 GCC 吗? 也许你应该开始删除代码块,直到它再次工作,这样你就可以找出是什么调用重现了它。不是一个干净的解决方案,但我已经解决了这样的问题。有点像在你的代码中进行二进制搜索,通过删除一些代码直到你缩小范围。 【参考方案1】:

这是使用我可以从您的回溯中提取的所有信息的初步猜测。

您很可能混合和匹配 gcc 版本、链接器和 libstdc++,从而导致主机上出现异常行为:

    libc 是系统的:/lib64/libc.so.6 libstdc++ 位于“ThirdParty”目录中 - 这是怀疑,因为它告诉我它可能会在其他地方用不同的目标编译 - /home/bbazso/ThirdParty/sources/gcc-4.2.4/x86_64-pc-linux-gnu/libstdc++-v3/ /opt 中的另一个 libstdc++:/opt/trx-HEAD/gcc/4.2.4/lib/gcc/x86_64-pc-linux-gnu/4.2.4/../../../../include/c++/4.2.4/bits/basic_string.h:491

此外,GCC 可能会混合系统的 ld 而不是自身,这可能会导致更奇怪的内存映射使用。

【讨论】:

+1。拥有 2 个 libstdc++(但是发生了这种情况)似乎很可能是问题的原因(或与原因相关)。在使用 GNU 的 std::string 实现时,我在跨 DSO 传递 std::strings 时遇到了问题(它对可能导致问题的空字符串进行了一些优化),而没有多个 libstdc++s 的额外复杂性。 我也想知道不使用发行版的原生 GCC 的动机。 谢谢!这似乎是一个很好的理由。我正在更改我的构建,以便我只使用一个 gcc,它将是来自本机发行版 ubuntu 的 gcc 4.2.4-5 的那个。另外,您能否更详细地了解空字符串的优化或将我指向提供有关此信息的站点?我有兴趣知道它对可能导致此类问题的空字符串的作用。再次感谢! 我更改了代码以全面使用相同的 gcc,但这仍然没有解决崩溃问题。优化理论似乎很有趣,但我还没有找到任何关于 gcc 4.2.4 中这种崩溃的已知问题?我确实知道,如果我在编译时添加 -fno-default-inline ,这可以消除崩溃,但我不知道为什么? @bbazso:你确定你的 GCC 版本使用的是它自己的自编译 libstdc++?【参考方案2】:

你能用一个基本的两行程序重复崩溃吗?

#include <string>

int main()

    std::string abc;
    abc = "testString";

如果崩溃,请发布您的确切编译/链接选项?

如果没有,请开始缩减您的代码。一次删除几行,直到错误消失。一旦您有一些其他更改,您可以添加导致崩溃并删除以使其消失,这应该可以帮助您找到问题。

【讨论】:

我用 -O2 和 -O0 完全测试过了。 @Tom - 好吧,接受我的下一个建议。开始削减其余代码,直到分配不再崩溃。【参考方案3】:

发生在我身上是因为将 malloc 用于具有 std::strings 作为数据成员的类。棘手。

【讨论】:

您能提供更多相关信息吗?我遇到了同样的问题,我怀疑这可能是原因,但我不明白将 malloc 用于具有 std::strings 作为数据成员的结构有什么问题。 事实证明,你不应该使用 malloc 来分配包含类之类的 C++ 代码的结构,因为 malloc 只接受一些字节并且不理解 C++ 的东西!你应该为这种事情使用 new 。感谢提醒 +1,如果在包含 std::string 的类/结构上使用原始内存操作 (memset) 也会发生这种情况(在 GCC/libstdc++ 中看到这一点在 clang/libc++ 中不会发生)【参考方案4】:

正如你所说,这是一种奇怪的行为。

老实说,我认为您正在浪费时间研究 std::strings 可能存在的错误。只要你用得好,字符串是绝对安全的。

无论如何,根据您提供的信息: 首先,您是否使用线程?可能是线程问题。 其次,您使用 valgrind 检查您的程序。你根本没有任何警告吗?

注意:valgrind 最关键的警告是无效读取和无效写入。

PS : 正如评论中所说,您可能应该使用 g++ 来编译 C++ 代码;)

【讨论】:

以上是关于C++ 程序在执行 std::string 分配时总是崩溃的主要内容,如果未能解决你的问题,请参考以下文章

std::string 通过索引分配似乎不起作用

如何在 C++ 中将整个文件读入 std::string?

C++ 向量分配器错误

我们可以控制向量数组(c++)中元素的内存分配吗?

C++ 字符数组分配错误

可能由于 std::string 堆分配而受文件解析线程影响的性能?