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

时间:2018-11-19 04:09:10

标签: 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;
}

1 个答案:

答案 0 :(得分:0)

  

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

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

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

  

将FILE指针发送到其他函数是否是错误的做法?

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

  

追加模式会导致任何问题吗?

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

  

下面的程序是SIC宏处理器,无需担心程序的逻辑,您可以识别引起SegFault的任何常见错误吗?

我看到的常见错误:

  1. 不检查fopen的结果(这会使您的程序崩溃,我没有创建所有必需的文件)。
  2. fscanf与非常小的输入缓冲区一起使用-如果您读取的字符串长于10个字符,则缓冲区溢出会变得异常丰富。有关如何避免这种情况的信息,请参见this answer