另外,程序在运行Linux的arm设备上运行,我可以在我指定的sig-seg处理程序中输出堆栈信息和寄存器值。 问题是我不能将-g选项添加到源文件中,因为由于性能降级,错误可能不会被重现。
使用-g
选项编译gcc
不会导致“性能降级”。 它所做的只是导致调试符号被包含在内; 它不影响优化或代码生成。
如果使用传递给sigaction()
的sigaction
结构的sa_sigaction
成员来安装SIGSEGV
处理程序,则传递给处理程序的siginfo_t
结构的si_addr
成员将包含错误地址。
我倾向于使用valgrind
表示泄漏和内存访问错误 。
这似乎工作http://tlug.up.ac.za/wiki/index.php/Obtaining_a_stack_trace_in_C_upon_SIGSEGV
static void signal_segv(int signum, siginfo_t* info, void*ptr) { // info->si_addr is the illegal address }
如果您担心在设备上加载的二进制文件上使用-g,则可能会在ARM设备上使用带有可执行文件版本的gdbserver,并在开发计算机上运行arm-gdb,可执行文件。 剥离的版本和未剥离的版本需要匹配才能做到这一点,所以这样做:
# You may add your own optimization flags arm-gcc -g program.c -o program.debug arm-strip --strip-debug program.debug -o program # or arm-strip --strip-unneeded program.debug -o program
您需要阅读gdb和gdbserver文档以了解如何使用它们。 这并不难,但也不像它那样精致。 主要是很容易意外地告诉gdb做一些事情,最终以为你本意做,所以它将切换到远程调试模式。
如果可能的话,您可能还想使用backtrace()函数,该函数将在崩溃时提供调用堆栈。 当C程序出现分段错误,总线错误或其他内存违规错误时,可以使用这种方式来转储堆栈,就像在高级编程语言中一样。
backtrace()在Linux和Mac OS X上均可用
如果-g选项使错误消失,那么知道它崩溃的位置不太可能有用。 它可能写入函数A中的未初始化的指针,然后函数B尝试合法地使用该内存并死亡。 内存错误是一个痛苦。