是什么导致C中出现分段错误(堆芯转储)?

是什么导致C中出现分段错误(堆芯转储)?,c,segmentation-fault,coredump,hamming-code,C,Segmentation Fault,Coredump,Hamming Code,我正在尝试用C编写一个汉明码程序。但是,在编译后尝试运行./a.out时,我总是遇到一个分段错误(内核转储)。它编译时没有错误,我知道在尝试寻址释放的空间或修改字符串文字时可能会发生此错误。我不相信我正在做这两件事,我只是有一个简单的矩阵,我正在填写和交叉检查。如果您对这个问题有任何见解,我将不胜感激,我已经在下面留下了我迄今为止的代码: 这是一个家庭作业问题,涉及创建一个汉明码程序来处理数据。dat输入和输出到一个文件,一个1和0的排序列表 #include <stdio.h> #

我正在尝试用C编写一个汉明码程序。但是,在编译后尝试运行./a.out时,我总是遇到一个分段错误(内核转储)。它编译时没有错误,我知道在尝试寻址释放的空间或修改字符串文字时可能会发生此错误。我不相信我正在做这两件事,我只是有一个简单的矩阵,我正在填写和交叉检查。如果您对这个问题有任何见解,我将不胜感激,我已经在下面留下了我迄今为止的代码:

这是一个家庭作业问题,涉及创建一个汉明码程序来处理数据。dat输入和输出到一个文件,一个1和0的排序列表

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

FILE *fp;
FILE *fpOut;

int main(int argc, char *argv[])
{
        fp = fopen(argv[1], "r");
        fpOut = fopen("sortedCodeWords.dat", "w");

        int temp;
        int numI = 0;
        int count = 0;

        char matrix1[7];

        if(fp == NULL)
                printf("File can not be opened");
        else
        {
                char ch = getc(fp);

                while(ch != EOF)
                {

                        matrix1[2] = ch;
                        ch = getc(fp);

                        matrix1[4] = ch;
                        ch = getc(fp);

                        matrix1[5] = ch;
                        ch = getc(fp);

                        matrix1[6] = ch;
                        ch = getc(fp);

                        ch = getc(fp);

                        if(ch == '\n')
                        {
                                for(int i = 2; i < 7; i++)
                                {
                                        if(matrix1[i] == '1')
                                            numI++;

                                        i++;
                                }

                                if(numI % 2 == 0)
                                        matrix1[0] = 0;
                                else
                                        matrix1[0] = 1;

                                numI = 0;

                                for(int i = 1; i < 7; i++)
                                {
                                        if(matrix1[i] == '1')
                                                numI++;
                                        if(matrix1[i+1] == '1')
                                                numI++;

                                        i++;
                                        i++;
                                }

                                if(numI % 2 == 0)
                                        matrix1[1] = 0;
                                else
                                        matrix1[1] = 1;

                                numI = 0;

                                for(int i = 4; i < 7; i++)
                                {
                                        if(matrix1[i] == '1')
                                                numI++;
                                }

                                if(numI % 2 == 0)
                                        matrix1[3] = 0;
                                else
                                        matrix1[3] = 1;
                                numI = 0;

                                for (int i = 0; i < 7; i++)
                                {
                                        fprintf(fpOut, "%s", matrix1[i]);
                                }

                                fprintf(fpOut, "\n");

                                ch = getc(fp);
                        }

                        count++;
                }
        }
}

#包括
#包括
#包括
文件*fp;
文件*fpOut;
int main(int argc,char*argv[])
{
fp=fopen(argv[1],“r”);
fpOut=fopen(“sortedDowords.dat”,“w”);
内部温度;
int numI=0;
整数计数=0;
char-matrix1[7];
如果(fp==NULL)
printf(“文件无法打开”);
其他的
{
char ch=getc(fp);
while(ch!=EOF)
{
matrix1[2]=ch;
ch=getc(fp);
matrix1[4]=ch;
ch=getc(fp);
matrix1[5]=ch;
ch=getc(fp);
matrix1[6]=ch;
ch=getc(fp);
ch=getc(fp);
如果(ch='\n')
{
对于(int i=2;i<7;i++)
{
if(matrix1[i]=“1”)
numI++;
i++;
}
如果(numI%2==0)
矩阵1[0]=0;
其他的
矩阵1[0]=1;
numI=0;
对于(int i=1;i<7;i++)
{
if(matrix1[i]=“1”)
numI++;
if(matrix1[i+1]=“1”)
numI++;
i++;
i++;
}
如果(numI%2==0)
matrix1[1]=0;
其他的
matrix1[1]=1;
numI=0;
对于(int i=4;i<7;i++)
{
if(matrix1[i]=“1”)
numI++;
}
如果(numI%2==0)
matrix1[3]=0;
其他的
matrix1[3]=1;
numI=0;
对于(int i=0;i<7;i++)
{
fprintf(fpOut,“%s”,matrix1[i]);
}
fprintf(fpOut,“\n”);
ch=getc(fp);
}
计数++;
}
}
}

我希望输出到一个文件。我并不总是会遇到这个错误,但当我从2D数组更改为1D数组时,我现在遇到了这个错误(我更改是因为我意识到这是不必要的)

我没有编译它,但我注意到的一件事是,它看起来好像你可能会离开数组的末尾,在那里循环到
I我看到的两件事。首先,在矩阵数组中混合字符和整数。其次,使用“%s”格式将矩阵的元素打印到文件中。“%s”需要一个以null结尾的字符串,其中当您传递字符和整数时。这将导致printf尝试访问超出边界的内存,从而导致故障。

如果要打印1和0,则应分配

matrix[i] = '1';
而不是

matrix[i] = 1;

你必须学会如何使用调试器

我将冒险假设您正在linux上工作,并逐步完成代码的调试过程

首先,我们在启用调试信息的情况下编译

james@debian:~/code$ gcc foo.c -g
现在,让我们用两个工具,valgrind和gdb来实现它


特别是valgrind是一个非常棒的工具,每当你使用内存出错时,它都会捕捉到。它实际上是跟踪内存泄漏的强制性工具,但可用于许多Seg故障。最重要的是,它易于使用,不需要交互

james@debian:~/code$ valgrind ./a.out foo.dat
==1857== Memcheck, a memory error detector
==1857== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1857== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==1857== Command: ./a.out foo.dat
==1857==
==1857== Conditional jump or move depends on uninitialised value(s)
==1857==    at 0x109381: main (foo.c:61)
==1857==
==1857== Invalid read of size 1
==1857==    at 0x4837C38: __GI_strlen (in /usr/lib/i386-linux-gnu/valgrind/vgpreload_memcheck-x86-linux.so)
==1857==    by 0x48A4786: vfprintf (vfprintf.c:1638)
==1857==    by 0x48AAC57: fprintf (fprintf.c:32)
==1857==    by 0x109437: main (foo.c:91)
==1857==  Address 0x1 is not stack'd, malloc'd or (recently) free'd
==1857==
==1857==
==1857== Process terminating with default action of signal 11 (SIGSEGV)
==1857==  Access not within mapped region at address 0x1
==1857==    at 0x4837C38: __GI_strlen (in /usr/lib/i386-linux-gnu/valgrind/vgpreload_memcheck-x86-linux.so)
==1857==    by 0x48A4786: vfprintf (vfprintf.c:1638)
==1857==    by 0x48AAC57: fprintf (fprintf.c:32)
==1857==    by 0x109437: main (foo.c:91)
==1857==  If you believe this happened as a result of a stack
==1857==  overflow in your program's main thread (unlikely but
==1857==  possible), you can try to increase the size of the
==1857==  main thread stack using the --main-stacksize= flag.
==1857==  The main thread stack size used in this run was 8388608.
==1857==
==1857== HEAP SUMMARY:
==1857==     in use at exit: 688 bytes in 2 blocks
==1857==   total heap usage: 3 allocs, 1 frees, 4,784 bytes allocated
==1857==
==1857== LEAK SUMMARY:
==1857==    definitely lost: 0 bytes in 0 blocks
==1857==    indirectly lost: 0 bytes in 0 blocks
==1857==      possibly lost: 0 bytes in 0 blocks
==1857==    still reachable: 688 bytes in 2 blocks
==1857==         suppressed: 0 bytes in 0 blocks
==1857== Rerun with --leak-check=full to see details of leaked memory
==1857==
==1857== For counts of detected and suppressed errors, rerun with: -v
==1857== Use --track-origins=yes to see where uninitialised values come from
==1857== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault
仅读取第一个错误,它在第61行标记一个问题,表示
如果(matrix1[i]='1')
正在使用未初始化的内存

在阅读代码时,记住这一点,就会发现
matrix1[1]
从未初始化过,因此存在一个bug。但这不是Seg的故障

第91行标记了另一个错误,看起来像是bug,但很难理解。所以让我们干掉gdb


info stack
打印执行堆栈。我们不关心系统文件级别的错误,我们关心main中的错误。
frame 3
切换到第#3帧,主功能位于该帧。在这一点上,您可能已经看到了错误,但如果不明显,我们可以深入挖掘

(gdb) info locals
i = 0
ch = 10 '\n'
temp = <optimized out>
numI = 0
count = 2
matrix1 = "\001\000\061\001\060\061\060"
(gdb)
在这一点上,你必须知道一些C。
matrix[0]
根本不是
printf(“%s”)
的合适参数。它需要一个指向某个有意义的值的字符指针,但您给它的是数字1,wh
(gdb) info stack
#0  __strlen_ia32 () at ../sysdeps/i386/i586/strlen.S:51
#1  0xb7e28787 in _IO_vfprintf_internal (s=0x4052c0, format=0x402037 "%s",
    ap=0xbffff52c "\360\021@") at vfprintf.c:1638
#2  0xb7e2ec58 in __fprintf (stream=0x4052c0, format=0x402037 "%s")
    at fprintf.c:32
#3  0x00401438 in main (argc=2, argv=0xbffff614) at foo.c:91
(gdb) frame 3
#3  0x00401438 in main (argc=2, argv=0xbffff614) at foo.c:91
91                          fprintf(fpOut, "%s", matrix1[i]);
(gdb)
(gdb) info locals
i = 0
ch = 10 '\n'
temp = <optimized out>
numI = 0
count = 2
matrix1 = "\001\000\061\001\060\061\060"
(gdb)
(gdb) print matrix1[0]
$1 = 1 '\001'
(gdb)
==1857==    by 0x109437: main (foo.c:91)
==1857==  Address 0x1 is not stack'd, malloc'd or (recently) free'd