微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在C代码中查找错误

更新:确实,依靠某个程序的段错误一个错误。 但是,我从这里收到的答复中感谢和学到了很多东西。

segfault.c

#include<stdio.h> #include<stdlib.h> /** * * This binary receives 2 numbers,an L and an R * * It will intentionally hit Segmentation Fault(actually SIGSEGV) whenever 30 is in the interval [L,R] * * It will be used to test the binary search segfault finder * */ int main(int argc,int **argv) { char exists; char *Q[3000]; int i; int L = atoi((char*)argv[1]); int R = atoi((char*)argv[2]); printf("L=%d R=%d",L,R); /*exit(0);*/ for(i=0;i<3000;i++) Q[i] = &exists; Q[30] = NULL; // <==== I want to cause a SIGSEGV through this ! for(i=L;i<=R;i++) { int T = *Q[i]; // <== will segfault when i == 30 because I said so :) }; };

automate.pl

#!/usr/bin/env perl use strict; use warnings; my $segfaulting_file = "s"; my $L = 0; my $R = 7266786; #`cat $segfaulting_file | wc -l`; my $M; my $binary = "./filter"; while ($L < $R) { $M = int(($L+$R)/2); # head argument for right side my $HL = $M; # tail argument for right side my $TL = $M-$L; # head argument for left side my $HR = $R; # tail argument for left side my $TR = $R-$M; print "M=$ML=$LR=$Rn"; my $go_left ; my $go_right; my $cmd_R = "cat $segfaulting_file | head -$HR | tail -$TR | $binary > /dev/null;"; my $cmd_L = "cat $segfaulting_file | head -$HL | tail -$TL | $binary > /dev/null;"; print "nRunning $cmd_Rn"; `$cmd_R`; #`./a.out $M $R`; print "RETVAL=$?n"; $go_right = ($? > 30000); # right side caused SEGFAULT `rm core`; print "nRunning $cmd_Ln"; `$cmd_L`; print "RETVAL=$?n"; #`./a.out $L $M`; $go_left = ($? > 30000); # left side caused SEGFAULT `rm core`; if( $L == $R ) { last; }elsif ( $go_left ) { print "GO left L=$LR=$Rn"; $R = $M ; }elsif ( $go_right ) { print "GO right L=$LR=$Rn"; $L = $M+1; }; }; # the loop stopped because $L==$R==$M,so we just print out $M print "Segfault caused by line $Mn";

在多个节点上发生MPI_Bcast错误

当Linux程序在C程序崩溃时,更好的debugging

MysqL_stmt_close时出现Segfault错误

是否有可能获得只包含调用堆栈,线程和本地variables的Linux核心?

“无法解释”核心转储

由pthread_kill引起的分割错误

从未定义长度的文件中读取,存储在数组中,分段错误

glGenTextures分段错误

wxPython崩溃与分割错误

分段错误:在buff> 4M时,在Ubuntu的C程序中堆栈分配

检测seg故障的最可靠方法可能是使用fork , exec和wait 。 你分叉Perl脚本; 孩子执行二进制。 父母从二进制文件中收集退出状态。 退出状态有两个部分 – 如果孩子退出控制,孩子退出的价值,或者如果孩子从一个信号中死亡,那么这个孩子收到的信号。 您只需检查信号分量是否为零; 如果不是零,则认为它是一个seg错误(尽管你可以验证它的数量,如果你愿意的话)。 剩下的技巧是获取二进制数据读取标准输入。 您可以让孩子启动一个读取的管道,并将管道复制到标准输入,然后关闭管道。 比真正困难更复杂。

概述Perl代码

我需要一个崩溃的程序,所以我创建了一个Perl脚本crash_after_reading :

#!/usr/bin/env perl use POSIX; $| = 1; print "." while (<>); print "n"; abort;

然后,你的Perl脚本的模拟器看起来像这样( forkwait.pl ):

#!/usr/bin/env perl use strict; use warnings; use POSIX; my $pipeline = "cat /etc/group"; my $pid; die "$!" if (($pid = fork) < 0); if ($pid == 0) { # Child open STDIN,"-|",$pipeline or die "open"; exec "crash_after_reading"; die "Failed to exec crash_after_reading"; } my $corpse = waitpid($pid,0); printf "PID = %d; status = 0x%.4Xn",$corpse,$?;

输出示例

.................................................................................. PID = 92413; status = 0x0006

低8位不为零,所以子程序与信号6(SIGABRT)一起坠毁。 如果低8位全部为零,则子程序以高8位的状态成功退出

如果您决定使用它,则需要将其适应于您的代码

你问Z为了解决Y为了解决X … 停止! 返回到X.您不需要日志行来解决为什么它分段。 你需要它隔离的源代码行来找出为什么它被隔离,我相信你知道如何得到。 从那一行开始,遵循它可能采取的任何分支,并策略性地放置assert()离子以确定错误输入来自哪里。 将重复的代码分离成重用的函数,继续“消除错误”,同时重构代码以实现模块化和稳定性。

编辑:如果你真的想继续这些行,你不需要一个perl脚本。 所有你需要的是在你的代码中的一个计数器来计算你分析它们的行数,以及信号的帮助。 当运行下面的代码, ideone不会segfault,直到计数是65535.希望你可以看到多么愚蠢的依靠segfaults缓冲区溢出是…

#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <limits.h> void segfault_handler(int sig); int counter = 0; int main(void) { int *fubar = malloc(0); // allocate ZERO bytes! assert(signal(SIGSEGV,segfault_handler) != SIG_ERR); assert(signal(SIGILL,segfault_handler) != SIG_ERR); assert(signal(SIGFPE,segfault_handler) != SIG_ERR); for (;;) { printf("Assigning to fubar[%d]n",counter); fubar[counter] = INT_MIN; counter = counter * 2 + 1; } } void segfault_handler(int sig) { /* NOTE: Using printf inside a signal handler is also undefined behavIoUr */ printf("Fault when counter is %dn",counter); exit(EXIT_FAILURE); }

由于您可以编辑过滤程序的来源,为什么不编辑它将每个日志文件行写入另一个文件,然后再处理它。 然后在段错误之后,查看新文件,看看当时正在处理的是哪一行。 这也将比你的二分查找更快,这​​将需要每次处理正好N-1行,而这种方法将平均处理N / 2行(取决于违规行的位置),其中有N日志文件中的行。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐