【问题标题】:bug "segmentation fault" in my c code我的 c 代码中的错误“分段错误”
【发布时间】:2012-11-27 01:00:04
【问题描述】:
#include<string.h>
#include<stdio.h>


int firstState(char s[], int length);
int secondState(char s[], int length);
int thirdState(char s[], int length);
int forthState(char s[], int length);

int main()
{
    char string[10];

    gets(string);

    if( firstState(string, 0) )
        printf("Accept\n");
    else
        printf( "Not accept\n" );

    return 0;
}

int firstState(char s[], int length)
{  
    if(s[length] == 'a')
        return (secondState(s, length++));
    else if(s[length] == 'b')
        return firstState(s, length++);
    else
        return 0;
}

int secondState(char s[], int length)
{  
    if(s[length] == 'a')
        return secondState(s, length++);
    else if(s[length] == 'b')
        return thirdState(s, length++);
    else
        return 0;
}

int thirdState(char s[], int length)
{  
    if(s[length] == 'a')
        return secondState(s, length++);
    else if(s[length] == 'b')
        return forthState(s, length++);
    else
        return 0;
}

int forthState(char s[], int length)
{  
    if(s[length] == 'a')
        return secondState(s, length++);
    else if(s[length] == 'b')
        return firstState(s, length++);
    else
        return 0;
}

它给了我一个分段错误或核心转储我很困惑!!! 有人可以解释为什么它给了我这种错误吗???? 并告诉我如何调试以使我的代码运行得非常清晰!!

我真的厌倦了这个:(

对不起我的英语不好

【问题讨论】:

  • 错误信息中是否包含行号?它指向哪里?
  • 您要测试的字符串是什么?
  • 您的平台是否包含调试器?
  • 你倾向于多次增加偏移量而不检查string的长度,这只是10!
  • 注意:所有的 xxxState() 函数都只能返回 0。如果它们返回,则无法获得返回 != 0。

标签: c segmentation-fault


【解决方案1】:

你有一个无限递归,

return (secondState(s, length++));

传递的length 参数是递增前length 的值,因此您只需要查看第一个char

length 参数作为length + 1 传递,并检查length 是否小于10(char 数组string 的长度)。

另一方面,

gets(string);

非常不安全,如果输入超过九个字符,则在分配的内存之外写入。使用

fgets(string, sizeof string, stdin);

改为。


好吧,既然只需要上面提到的修复和一个返回值的变化,大部分逻辑是正确的,固定代码:

// #include<string.h> <- We don't use that
#include<stdio.h>

// Match the grammar (a+b)*abb

int firstState(char s[], int length);    // nothing of the suffix matched
int secondState(char s[], int length);   // matched one character of the suffix
int thirdState(char s[], int length);    // matched two
int forthState(char s[], int length);    // matched the complete suffix

int main()
{
    char string[10];
    // Get a 0-terminated string into the buffer.
    fgets(string, sizeof string, stdin);

    if( firstState(string, 0) )
        printf("Accept\n");
    else
        printf( "Not accept\n" );

    return 0;
}

int firstState(char s[], int length)
{  
    if(s[length] == 'a')  // first character of suffix matched
        return (secondState(s, length+1));
    else if(s[length] == 'b')  // nothing matched
        return firstState(s, length+1);
    else    // end of string in not-accepting state
        return 0;
}

int secondState(char s[], int length)
{  
    if(s[length] == 'a')  // the old matched 'a' wasn't part of the suffix, the new may be
        return secondState(s, length+1);
    else if(s[length] == 'b') // now matched two characters of the suffix
        return thirdState(s, length+1);
    else    // end of string in not-accepting state
        return 0;
}

int thirdState(char s[], int length)
{  
    if(s[length] == 'a')  // last three chars aba, the last 'a' could be part of the suffix
        return secondState(s, length+1);
    else if(s[length] == 'b')  // full suffix matched
        return forthState(s, length+1);
    else    // end of string in not-accepting state
        return 0;
}

int forthState(char s[], int length)
{  
    if(s[length] == 'a')  // another char, start a new candidate for the suffix
        return secondState(s, length+1);
    else if(s[length] == 'b')  // another char, can't be part of the suffix, start over
        return firstState(s, length+1);
    else        // end of string in accepting state, yay!
        return 1;
        // return s[length] == '\0';
        // if characters other than 'a' and 'b' need not signal the end of the string
}

【讨论】:

  • 第 26 行:3059 总线错误 stdbuf --error=0 --output=0 "$@"
  • 究竟是什么产生了该错误消息?看起来不像我收到的任何错误消息,操作系统是什么?
  • 我的代码是现在接受与这个正则表达式 (a+b)*abb 匹配的任何字符串,当我输入 abb 时,它会打印 Not accept,这是错误的,它应该打印 accept
  • “任何字符串”和 Kleene 星号一起使这有点困难,因为您不知道字符串会有多长。所以也许需要对输入进行char-wise 读取。不管怎样,你知道如何编写一个简单的状态机吗?不要递归调用函数,而是在循环中执行,更改state 变量?
【解决方案2】:

Segmentation Fault 是访问冲突,即当程序尝试访问内存时,它不应该是 http://en.wikipedia.org/wiki/Segmentation_fault

在您的情况下,它是由不安全的数组索引引起的,例如

int firstState(char s[], int length)
{
...
return firstState(s, length++);
...
}

您实际上并没有检查新长度是否仍在范围内,因此如果字符串不是以空值结尾的,在您的情况下可能不是,那么您将有一个无限循环,导致 SegFault。

对于调试,使用 GUI 将是最明智的方法,在 Windows 上尝试 Visual Studio,在其他一切上尝试 Eclipse。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    相关资源
    最近更新 更多