【问题标题】:Segmentation fault error when returning the function返回函数时出现分段错误错误
【发布时间】:2017-07-06 06:25:51
【问题描述】:

所以,我正在为 LC3b 机器编写解释器。我需要编写一个函数来检查输入是否是有效的操作码。为此,我编写了如下函数:

int isOpcode(char* oput)//oput=Opcode under test
{
  FILE* isa_file = NULL;
  int i,j;
  char * line = NULL;
  size_t len = 0;
  ssize_t nread;

  //printf("Entered opcode checking function \n");
  /*convert to lower case */
  //for( i = 0; i < strlen( oput ); i++ )
  //    oput[i] = tolower( oput[i] );
  //printf("Entered opcode checking function1 \n");

  /*for modularity, using the file */
   isa_file = fopen("isa", "r");
   if(isa_file == NULL)
       printf("Error in file opening\n");
   int flag;
   while ((nread = getline(&line, &len, isa_file)) != -1)
   {
       printf("Retrieved line of length %zu :\n", nread);
       printf("%s", line);  
       //Solving the new line character problem which resulted in the improper difference of strcmp ..now it is proper...
       //char final[strlen(line)-1];
       //strcpy(final,line);
       //final[strlen(line)-1]='\0'; 
       //  printf("Entered opcode checking function2 \n");
       //  printf("%s \n",oput);
       // overwrite \n with nul-terminator
       line[strcspn(line, "\n")] = 0;
       char final[strlen(line)];
       strcpy(final,line);
       flag=strcmp(oput,final);
       printf("%s \n",oput);
       printf("flag: %d \n",flag ); 
       if(flag < 0 || flag >0)
       {
           flag=-1;
           //printf("entered 1st condition \n");
           printf("final flag: %d \n", flag);
        }
       else 
       {
           flag=1;
           //printf("entered negative \n");
           printf("final flag: %d \n", flag);
           break;
       }

   }
   printf("end of loop \n");//this is not getting printed
   fclose(isa_file);
   if (line)
       free(line);
   return flag;
}

现在,当我使用其中一个有效操作码调用函数时,函数会打印最终标志 (=1),然后进入分段错误。它甚至不打印循环语句的结尾。有人可以告诉我有什么问题吗?我尝试将这个函数的一部分作为单独的文件执行,它似乎工作得很好。


更新: 当我注释掉 toLower 代码时,循环语句的结尾现在会打印在屏幕上。但是,即使这样,代码也会引发段错误。有趣的是,仅当最终标志设置为 1 时才会引发错误。否则,它可以正常工作!我无法理解这个奇怪的问题!

【问题讨论】:

  • final[strlen(line)-1]='\0'; 不是减一吗?
  • 并在调用fopen后检查isa_file是否为NULL
  • return flag;应该是free和file close之后,明显是检查文件是否正确打开和行分配
  • char final[strlen(line)-1]; 关闭 2 ==> char final[strlen(line)+1];
  • 不要使用名为read的对象,有一个同名的函数。我们通常将其命名为 nread 以表示读取的字节数。

标签: c segmentation-fault


【解决方案1】:

在您发表评论后,我可以说:

strlen 已经为您提供了读取字符-1 的长度,因为不计算nul-terminator。此外,您不能使用strcpy 来做您需要做的事情,因为它会将源字符串的所有字符复制到一个较小的字符串中,从而导致 UB。

你可以做的是删除源字符串中的'\n',然后复制它,比如:

// overwrite \n with nul-terminator
line[strcspn(line, "\n")] = 0;
// allocate new string less by one
char final[strlen(line)+1];
// allocate new string less by one
strcpy(final,line);

【讨论】:

  • 你不认为 char final[strlen(line)+1];应该是 char final[strlen(line)];我相信是这样,因为说:line=origin\n 并且在用 NULL 覆盖 \n 后,strlen(line) 将为 6。现在,我只需将其复制到大小为 6 的 final 中。但是,我尝试了这两种方法,但错误仍然存​​在!
  • @YashKarundia 否。对于 6 字符字符串,您需要 7 字符数组,因为您需要空终止符的空间..
【解决方案2】:

以下建议的代码:

  1. 干净编译
  2. 不会链接,因为没有main()函数
  3. 应用所有 cmets

现在建议的代码:

#include <stdio.h>  // printf(), FILE, fopen(), fclose(), perror()
#include <string.h> // strcpy(), strchr()
#include <stdlib.h> // malloc(), free(), exit(), EXIT_FAILURE
#include <ctype.h>  // tolower()

int isOpcode(char* oput);

int isOpcode(char* oput)//oput=Opcode under test
{
    FILE* isa_file = NULL;
    //int i;  <-- unused
    //int j;  <-- unused



    //printf("Entered opcode checking function \n");
    /*convert to lower case */
    for( size_t i = 0; i < strlen( oput ); i++ )
        oput[i] = (char)tolower( oput[i] );
    //printf("Entered opcode checking function1 \n");

    /*for modularity, using the file */
    isa_file = fopen("isa", "r");

    if(isa_file == NULL)
    {
        perror( "fopen to open 'isa' for read, failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    int flag;
    char * line = NULL;
    size_t len = 0;
    ssize_t nread;

    while ((nread = getline(&line, &len, isa_file)) != -1)
    {
       printf("Retrieved line of length %zu :\n", nread);

       printf("%s", line);

       //Solving the new line character problem which resulted in the improper difference of strcmp ..now it is proper...
       char final[ nread+1 ];
       strcpy(final, line);

       //  printf("Entered opcode checking function2 \n");
       //  printf("%s \n",oput);
       // overwrite \n with nul-terminator
       char *newline = NULL;
       if( NULL != (newline = strchr( final, '\n' ) ) )
           *newline = '\0';

       printf("%s \n",oput);
       printf("flag: %d \n",flag );

       strcmp(oput,final);
       switch( strcmp(oput,final) )
       {
            case -1:
            case 1:
               flag=-1;
               //printf("entered 1st condition \n");
               printf("final flag: %d \n", flag);
               break;

            case 0:
               flag=1;
               //printf("entered negative \n");
               printf("final flag: %d \n", flag);
               break;

           default:
               break;
        }

        free( line );
        line = NULL;
        len = 0;
    }

    if( !feof( isa_file ) )
        perror( "getline failed" );

    printf("end of loop \n");//this is not getting printed
    fclose(isa_file);


    free(line);

    return flag;
}

我不确定这是否是您正在寻找的功能。

【讨论】:

  • 注意数组final[]可以通过对getline()设置的数组做所有处理来完全消除
  • 虽然其余代码看起来不错,但我无法理解 switch 案例。我想比较输出和最终。如果两者相等,我需要将标志返回为 1,否则返回 -1。在您提出的代码中,开关盒不执行该功能,因为 strcmp 不会总是返回“-1”。它返回两个字符串之间的差异。
  • @YashKarundia,然后将switch()语句替换为if( 0 == strcmp(oput,final) ) { // handle match } else { // handle mis-match }
猜你喜欢
  • 1970-01-01
  • 2018-09-03
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多