如何查找使用工具时不会发生的段错误
How to find seg fault which doesn't occur when using tools
我问这个是因为如果我使用 Valgrind 或 GDB 运行 我的 C++ 程序中不会出现段错误。但是一旦我 运行 它是独立的,它就很容易重现,因为它会毫无错误地分割错误。我已经把部分代码注释掉了运行,但我仍然找不到确切的原因。我担心它发生得更早,只是出现得晚。
更新:
澄清一下,这是 Linux.
上的 C++ 17
确保你没有禁用核心转储(ulimit -c unlimited
,虽然有 other config options 是相关的),然后当你的程序崩溃时,你应该得到一个核心转储文件。
运行 gdb program core
来分析核心转储——gdb 看起来就像您已将它用于 运行 您的程序,并且它遇到了停止它的信号。您可以执行回溯以查看堆栈、检查变量和内存等。
好坏老printf
调试:)。让你的程序在崩溃点附近放置面包屑(以控制台输出的形式,或写入日志)。当您对崩溃点的位置有了更好的了解时,请使面包屑更紧密。假设你的崩溃是相当确定的,这最终会收敛到崩溃点。
另一种技术,为 SIGSEGV 安装信号处理程序。一旦信号触发,转储崩溃点寄存器,然后使用 addr2line
之类的东西将 IP 地址转换为源代码行。您需要模块的起始地址。
在我看来,这是典型的比赛条件。您在代码中使用任何线程吗?如果是这样,请考虑在访问某些可能在其他线程中使用的数据时使用 std::mutex
。
我总是只能使用大量的调试打印来调试这些东西,但要注意,它们也会稍微减慢你的代码并消除竞争条件。
我问这个是因为如果我使用 Valgrind 或 GDB 运行 我的 C++ 程序中不会出现段错误。但是一旦我 运行 它是独立的,它就很容易重现,因为它会毫无错误地分割错误。我已经把部分代码注释掉了运行,但我仍然找不到确切的原因。我担心它发生得更早,只是出现得晚。
更新: 澄清一下,这是 Linux.
上的 C++ 17确保你没有禁用核心转储(ulimit -c unlimited
,虽然有 other config options 是相关的),然后当你的程序崩溃时,你应该得到一个核心转储文件。
运行 gdb program core
来分析核心转储——gdb 看起来就像您已将它用于 运行 您的程序,并且它遇到了停止它的信号。您可以执行回溯以查看堆栈、检查变量和内存等。
好坏老printf
调试:)。让你的程序在崩溃点附近放置面包屑(以控制台输出的形式,或写入日志)。当您对崩溃点的位置有了更好的了解时,请使面包屑更紧密。假设你的崩溃是相当确定的,这最终会收敛到崩溃点。
另一种技术,为 SIGSEGV 安装信号处理程序。一旦信号触发,转储崩溃点寄存器,然后使用 addr2line
之类的东西将 IP 地址转换为源代码行。您需要模块的起始地址。
在我看来,这是典型的比赛条件。您在代码中使用任何线程吗?如果是这样,请考虑在访问某些可能在其他线程中使用的数据时使用 std::mutex
。
我总是只能使用大量的调试打印来调试这些东西,但要注意,它们也会稍微减慢你的代码并消除竞争条件。