c - 使用文件指针时如何处理段错误?

标签 c segmentation-fault

如何确定 SegFault 代码中的问题出在哪里?

  1. 将 FILE 指针发送到其他函数是一种不好的做法吗?
  2. 附加模式会导致任何问题吗?

下面的程序是一个SIC宏处理器,不用担心程序的逻辑,你能识别出导致SegFault的常见错误吗?

Input.txt(唯一的输入文件,其余文件由程序创建)

SAMPLE  START   1000
MACROS  MACRO   -
SUM     MACRO   &A,&B,&C
-       LDA     &A
-       ADD     &B
-       MOV     &C,&A
-       MEND    -
DIF     MACRO   &A,&B,&C
-       LDA     &A
-       SUB     &B
-       MOV     &C,&A
-       MEND    -
-       MEND    -
-       SUM     TWO,ONE,APLHA
-       SUB     TWO,ONE,BETA
ONE     WORD    1
TWO     WORD    2
ALPHA   RESW    1
BETA    RESW    1
-       END     -

如果我在代码块中运行它,它只会创建文件 inter.txt,但之后不会执行任何操作。我尝试在第一次打开 inter.txt 后立即向其添加一行,但这也没有发生(仅创建空文件)

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
void processline(FILE**,FILE**);
void define();
void expand();
char label[10],mn[10],oper[10];

void macrop()
{
    FILE *finter;
    finter=fopen("inter.txt","a+");
    fprintf(finter,"HI");
    FILE *f;
    f=fopen("input.txt","r");
    fscanf(f,"%s%s%s",label,mn,oper);
    fprintf(finter,"%s\t%s\t%s",label,mn,oper);
    fscanf(f,"%s%s%s",label,mn,oper);
    while(strcmp(mn,"END")!=0)
    {
        processline(&f,&finter);
        fscanf(f,"%s%s%s",label,mn,oper);
    }
    fprintf(finter,"%s\t%s\t%s",label,mn,oper);
    fclose(finter);
    fclose(f);
}

void processline(FILE** f,FILE** finter)
{
    FILE *fnam;
    unsigned long int p;
    char name[10];
    fnam=fopen("namtab.txt","r");
    fscanf(fnam,"%s %lu",name,&p);
    while(!feof(fnam))
    {
        if(strcmp(name,label)==0)
        {
            expand(finter,p);
            fclose(fnam);
            return;
        }
    fscanf(fnam,"%s%lu",name,&p);
    }
    if(strcmp(mn,"MACRO")==0)
    {
        fclose(fnam);
        define(f);
    }
    else
    fprintf(*finter,"%s\t%s\t%s",label,mn,oper);
    fclose(fnam);
}
void define(FILE** f)
{
    char *token;
    char *args[10];
    int level,j,i;
    i=0;
    level =1;
    FILE *fdef,*fnam;
    fdef=fopen("deftab.txt","a+");
    fnam=fopen("namtab.txt","a+");
    fprintf(fnam,"%s\t%lu\n",label,ftell(fdef));
    while(level>0)
    {
        fscanf(*f,"%s%s%s",label,mn,oper);
        if(strcmp(mn,"MACRO")==0)
        {
            level+=1;
            fprintf(fnam,"%s\t%lu\n",label,ftell(fdef));
            token=strtok(oper,",");
            while(token!=NULL)
        {
                args[i]=token;
                token=strtok(NULL,",");
                i++;
        }
        }
        else if(strcmp(mn,"MEND")==0)
        {
            level-=1;
            i=0;
            fprintf(fdef,"%s\t%s\t%s\n",label,mn,oper);
        }
        else
        {
        fprintf(fdef,"%s\t%s\t",label,mn);
        token=strtok(oper,",");
        while(token!=NULL)
        {
                if(token[0]=='&')
                {
                    j=0;
                    while(strcmp(token,args[j])!=0)
                    {
                        j++;
                    }
                    fprintf(fdef,"?%d",j);
                }
                else
                {
                fprintf(fdef,"%s\n",token);
                }
            }
        }

    }
    fclose(fdef);
    fclose(fnam);
}
void expand(FILE **finter,unsigned long int p)
{
    FILE * fdef;
    int i,c;
    i=0;
    c=0;
    char * args[10];
    char l[10],m[10],o[10];
    char *token;
    token=strtok(oper,",");
    while(token!=NULL)
    {
        args[i]=token;
        token=strtok(NULL,",");
        i++;
    }
    fdef=fopen("deftab.txt","r");
    fseek(fdef,p,SEEK_SET);
    fscanf(fdef,"%s%s%s",l,m,o);
    while(strcmp(m,"MEND")!=0)
    {
        c=0;
        fprintf(*finter,"%s\t%s\t",l,m);
        token=strtok(o,",");
        while(token!=NULL)
        {
           if(token[0]=='?')
           {
               if(c==1)
               fprintf(*finter,",");
               char a[2];
               a[0]=token[1];
               a[1]='\0';
               fprintf(*finter,"%s",args[atoi(a)]);
    }
            else
            {
                if(c==1)
                fprintf(*finter,",");
                fprintf(fdef,"%s",token);
            }
            c++;
            token=strtok(NULL,",");
        }
        fprintf(*finter,"\n");
        fscanf(fdef,"%s%s%s",l,m,o);
    }
fclose(fdef);
}
int main()
{
    macrop();
    return 0;
}

最佳答案

How can I identify where the problem in the code with SegFault is?

您在调试器下运行它。在 Linux 上,GDB是最常用的一种。 LLDB也可以使用。

如果您使用的是受支持的平台,您还可以使用 Address Sanitizer 构建您的程序(-fsanitize=address),这可能会直接指出您的错误。

Is it a bad practice to send FILE pointers to other functions?

一点也不。不过传递 FILE ** 是很不寻常的。

Does append mode cause any problem?

可能不是。您的程序需要一堆输入文件,而您没有提供它们的内容,因此无法判断您的程序在哪里崩溃。

Following program is a SIC macro processor, without worrying about the logic about the program can you identify any common errors causing SegFault?

我看到的常见错误:

  1. 不检查 fopen 的结果(这会导致您的程序崩溃——我没有创建所有必需的文件)。
  2. 在非常小的输入缓冲区中使用 fscanf - 如果您读取的字符串超过 10 个字符,则会出现大量缓冲区溢出。请参阅this answer关于如何避免这种情况。

关于c - 使用文件指针时如何处理段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53368186/

相关文章:

c - C 中的 SIGSEGV(段错误)

C 管道分段故障

c - 一次从 std 获取一个字符的输入 (C)

C 预处理器定义每个字节都是 0xFF 的给定类型的值?

C - fscanf 混合数字和静态文本

ios - 分段故障 Swift 2 App

c - 当我使用 N=1023 而不是 1024 时,为什么在下面的程序中会出现段错误(核心已转储)?

C 系统函数在其他字符串之前获取

c - c中的后减量

c - 段错误和共享库使用 - Vega 7000 POS