【问题标题】:My program gives the correct output in windows(gcc) but in Linux(gcc) it leads to segmentation fault我的程序在 windows(gcc) 中给出了正确的输出,但在 Linux(gcc) 中会导致分段错误
【发布时间】:2018-07-04 17:27:52
【问题描述】:

这个程序是找到 NFA 的所有状态的 epsilon 闭包。我已经使用堆栈来完成这项工作。当我使用 gcc 编译并运行 Windows 10(命令提示符)时,该程序给出了正确的输出。但是当我使用相同的编译器编译并在 Linux 中运行它时,会导致分段错误。我已经为此使用了任何动态内存分配。

我尝试使用 gdb 进行调试,但无法找到问题所在。在显示转换矩阵时在 printf("\n") 之后检测到分段错误。 这对于有人可以找到故障非常有帮助。提前致谢。

输入是从文件中读取的:nfa.txt。

//states
q0 q1 q2
//input_symbols 
0 1
//start_state       
q0
//final_state       
q2      
//transitions of the form : intial_state  input  final_state
q0 0 q0     
q0 e q1
q1 1 q1     
q1 e q2
q2 2 q2

输出如下:

232 表示零跃迁(Φ),ε 表示 -1。

States:
q0
q1
q2
Transitions read
232  0    1    2    -1
0    0    232  232   1
1    232  1    232   2
2    232  232  2     232

e-closure(0) : 0 1 2
e-closure(1) : 1 2
e-closure(2) : 2

请耐心等待,因为这是一个相当长的程序。

#include <stdio.h>     
#include <string.h>     //REMEMBER ME WHILE I'M GONE 
#include <errno.h>
#include <stdlib.h>

FILE *file;
int  numberOfStates = 0;
int  flag = 0;
int  states[20];

int  j = 0;
int  i = 0;
int  k = 0;

char a[20];

int  transitions[4][5];
int  visited[10];

int  MAXSIZE = 8;       
int  stack[8];     
int  top = -1;            

int isempty()
{
   if(top == -1)
      return 1;
   else
      return 0;
}

int isfull()
{
   if(top == MAXSIZE)
      return 1;
   else
      return 0;
}

int pop() 
{
   int data;

   if(!isempty()) {
      data = stack[top];
      top = top - 1;   
      return data;
   }
   else
         printf("Could not retrieve data, Stack is empty.\n");
 }


int push(int data) {

   if(!isfull()) {
      top = top + 1;   
      stack[top] = data;
   }
   else 
      printf("Could not insert data, Stack is full.\n");
}

int IsVisited(int edge)
{
    for(int i = 0; i < 10; i++)
        if(visited[edge] == 1)
            return 1;

    return 0;
}

void epsilon_closure(int state)
{
    int  e_closure[10];


    for(int i = 0; i < 10; i++ )
    {   e_closure[i] = -1;
        visited[i] = 0;
    }

    push(state);
    visited[state] = 1;

    while(top != -1)
    {
        int u = pop();

        j = 1;
        while(j < 5)
        {
            //if there is an epsilon transition from the state 'u' to 'v'
            if(transitions[j][0] == u && transitions[j][4] != 232) //ASCII of Φ = 232
            {
                if(! IsVisited(transitions[j][4]))
                {
                    visited[transitions[j][4]] = 1;
                    push(transitions[j][4]);
                }

            }
            j++;
        }
    }

    j = 0;
    for(int edge = 0; edge < 10; edge++)
    {
        if(visited[edge] == 1)
            e_closure[j++] = edge;
    }
    printf("e-closure(%d) : ",state);
    for (i = 0; e_closure[i] != -1; ++i)
        printf("%d ", e_closure[i]);
    printf("\n");
} 

int main()
{
    file = fopen("nfa.txt","r");

    if (file == NULL) {
        perror("fopen");
        return -1;
    }


    //Reading the states 
    while(!feof(file))
    {
        fscanf(file,"%s",a);
        if(strcmp("//states",a) == 0)
            flag = 1;
        else if(strcmp("//input_symbols",a) == 0)
            break;
        if (flag == 1 && a[0] != '/')
        {
            states[i++] = a[1] - '0';

        }
        numberOfStates = i; 
    }

    //Display the states of the e-NFA
    printf("\nStates : \n");
    for(i = 0; i < numberOfStates; i++ )
    {   
        printf("q%d\n",states[i]);
    }

    i = 1;
    flag = 0;
    //Reading the transition table

    for(int i = 0; i < 4; i++){
        for(int j = 0; j < 5; j++)
        {
            transitions[i][j] = 232;
        }

    }   
    while(!feof(file))
    {
        fgets(a,100,file);
        if(a[0] == '/')
        {   
            flag = 1;
        }
        if(flag == 1 && a[0] != '/')
        {   
            j = 0;
            //found a way to store the transition table in a matrix
            if(a[3] == 'e')
                transitions[(a[1] - '0') + 1][4] = a[6] - '0';

            else    
                transitions[(a[1] - '0') + 1][(a[3] - '0') + 1] = a[6] - '0';
            if(a[3] != 'e')
                transitions[0][a[3] - '0' + 1] = a[3] - '0';        //input
            else
                transitions[0][4] = -1;     // epsilon input
            transitions[(a[1] - '0') + 1][0] = a[1] - '0'; //initial state

        }
    }
    printf("\nTransitions read\n");
    for(int i = 0; i < 4; i++){
        for(int j = 0; j < 5; j++)
        {
            printf("%d\t",transitions[i][j]);
        }
        printf("\n"); //detected segmentation fault here
    }   

    //Calling e-closure for all the states  
    for(k = 0; k < numberOfStates; k++)
    {
        epsilon_closure(states[k]);
    }

    return 0;
}

【问题讨论】:

  • 调试它。并确保您的索引不会超出数组的范围。这似乎是这里出现段错误的唯一可能原因。
  • 啊……还有这个:while(!feof(file))Why is “while ( !feof (file) )” always wrong?
  • "请耐心等待,因为这是一个相当长的程序。" 不,请发minimal reproducible example
  • 您的全局i 和几个本地循环i 的混合并不能完全帮助澄清这一点,顺便说一句。同样适用于j
  • 编译时,始终启用警告,然后修复这些警告。 (对于gcc,至少使用:-Wall -Wextra -Wconversion -pedantic -std=gnu11

标签: c gcc segmentation-fault nfa


【解决方案1】:

这里有个bug:

int push(int data) {

   if(!isfull()) {
      top = top + 1;   
      stack[top] = data;  
   }
   else 
      printf("Could not insert data, Stack is full.\n");  
}

如果top == MAXSIZE-1isfull() 将返回 false,那么您将 top 递增到 MAXSIZE 并分配 stack[MAXSIZE] 超出范围并调用 UB。没有检查完整的源代码,我可以想象在分配后递增top 是正确的,或者如果top &gt;= MAXSIZE-1 则您必须更改isfull() 以返回true

【讨论】:

  • 值得注意的是,这个函数也声明了一个int返回类型,但没有做任何尝试来实现它。 pop 的控制路径之一也发生了类似的问题,这更加灾难性,因为它的返回结果实际上被调用者使用。
  • 感谢您指出...该程序现在可以按预期处理输入。但是 push 或 pop 不是问题。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-29
  • 1970-01-01
  • 2016-03-02
  • 1970-01-01
  • 1970-01-01
  • 2017-03-11
  • 1970-01-01
相关资源
最近更新 更多