在将调试语句重定向到stderr时出现了奇怪的情况
Strange situation while redirecting debug statements to stderr
我被困在一个情况。我正在研究嵌入式设备(基于linux操作系统和ARM处理器,32位)。它是一种触摸屏设备,有许多外围设备,如智能卡读卡器,GPS, GPRS。我在C编码和我的应用程序崩溃后一段时间,当我重定向我的调试语句如下所示。我有大约300个调试打印语句,我使用这个函数像宏一样打印。设备也可以通过USB线连接到系统终端。当我在系统终端中打印这些调试语句时,应用程序不会在任何地方崩溃,但是当我不使用计算机终端并在设备中运行应用程序时,它会在一段时间后崩溃:
#ifdef DEBUG_TEST
#define DEBUG_TEST 1
#else
#define DEBUG_TEST 0
#endif
#define DEBUG_PRINT(fmt, ...)
do { if (DEBUG_TEST) fprintf(stderr, fmt, ##__VA_ARGS__); } while (0)
但是当我关闭这些调试语句时,应用程序不会在任何地方崩溃。我不明白为什么会这样。
根据我的猜测,由于设备没有自己的标准终端,因此打印这些调试消息正在创建一个缓冲区,由于它在一段时间后崩溃,而另一方面,当我关闭调试语句时,它工作得很好。请说明为什么会发生这种情况?
也许你的DEBUG_PRINT调用的一个参数导致fprintf的字符串插值器例程引用无效内存?例如,在你的代码中,像这样的代码会使你的应用程序在fprintf():
中崩溃。const char * badPointer = (const char *) 0xDEADBEEF; // deliberately pointing to invalid memory
DEBUG_PRINT("Crashing now! %sn", badPointer);
…要么是这样,要么是系统的studio或USB实现中存在导致崩溃的错误。
为了缩小范围,您可以尝试注释掉各种DEBUG_PRINT语句,直到崩溃消失(此时您可以合理地怀疑是现在被注释掉的DEBUG_PRINT语句之一导致了崩溃,并重新注释一些,直到找出罪魁祸首是谁)……或者,如果您怀疑fprintf()中有bug,您可以执行如下的酷刑测试:
while(1) DEBUG_PRINT("I think I %s!n", "can");
…然后看看运行它是否会给您预期的输出(字符串的无限输出)或崩溃。如果它崩溃了,那就说明程序之外有bug。
您是在更改这些语句,还是从调试到发布版本?从调试版本切换到发布版本会改变诸如优化和内存填充之类的事情,所以你的崩溃可能发生在非调试中,因为这些。
如果你所改变的只是调试跟踪开关,我建议你非常仔细地检查你所有的格式参数(%s, %d等),并确保你没有传递一个错误类型的变量
如何在没有控制终端的情况下运行应用程序?您可以尝试以下操作:
在终端连接的情况下运行应用程序,但是stderr重定向
./yourapp 2>/dev/null
或
./yourapp 2>somefile.log
,看看它是否仍然崩溃。如果你想转储一个核心文件,不要忘记执行ulimit -c unlimited。
如果您有一个基于busybox的用户空间,您可以尝试在循环缓冲区模式下使用syslogd,并通过调用syslog来替换fprintf(stderr,…),并查看它是否仍然崩溃。
- 如何针对特定情况调试和修复此双自由内存损坏问题
- 如何在添加文件的情况下在VSCode中调试C++程序
- 调试断言仅在某些情况下失败?C++
- 在没有 -g 选项的情况下编译,但我想获得更详细的调试信息
- 在这种情况下如何调试动态库
- 我的调试器说我有一个隔离错误错误,但无法告诉我在哪里,在非常特殊的情况下发生
- SIGABRT 运行时何时出现错误以及如何在这种情况下进行调试
- 例外情况下,我希望在没有任何堆栈展开的情况下进行调试
- 程序在没有调试符号的情况下崩溃,运行良好(两种情况下都没有优化或任何内容)
- 为什么在VS 2010 C++中,我的程序在调试器中运行良好时会崩溃,但在没有调试器的情况下运行时会崩溃
- OpenGL错误只在未经调试的情况下运行时出现,怎么可能呢
- 在不调试的情况下启动,与从.exe启动相同
- 如何在不调试符号的情况下确定从外部库引发的异常
- 链表程序挂在代码块调试器下,但在其他情况下正常执行
- PDB无法显示发布版本崩溃的确切行号,但在二进制调试版本的情况下显示精确行号
- 为什么谷歌破板不能处理所有崩溃?如何调试这些情况
- 如何在没有调试符号和优化的情况下创建 cmake 构建配置
- 大多数为 Qt 5.3.2 编译的二进制文件都是在没有调试信息的情况下构建的
- 在没有源代码的情况下使用gdb进行调试
- 如何在没有文件、objdump或gdb的情况下知道二进制文件是否包含调试符号