编译良好的C程序中的分段错误

时间:2013-02-02 01:22:14

标签: c

我正在解决USACO的一个问题。在这个问题中,我必须将两个字符串作为输入并计算模数为47的数值。如果值相同,则打印GO,否则必须打印STAY。初始数值将通过取字母数字的乘积来计算(A为1,Z为26),然后使用模数计算最终数字。

我的程序正在编译时出现任何错误并在我的计算机上运行良好。但是,它将分段错误显示为分级计算机的执行错误。程序和输出如下: -

程序: -

#include<stdio.h>
#include<string.h>
main()
{
    int cal(char *ptr);
    char *comet,*group;
    int a,b;
    scanf("%s",comet);
    a=cal(comet);
    scanf("%s",group);
    b=cal(group);
    if(a==b)
        printf("GO");
    else
        printf("STAY");
    return 0;
}
int cal(char *ptr)
{
    int i=0,c,prod=1,mod;
    while(ptr[i]!='\0')
        {
            if(ptr[i]>='A'&&ptr[i]<='Z')
            {
                c=ptr[i]-'@';
                prod=prod*c;
                i++;
            }
        }
    mod=prod%47;
    return mod;
}

输出: -

enter image description here

我的问题是如何查明分段错误。我已经读过这个错误,但不知道在这个程序中该怎么做。任何帮助都会很棒。

5 个答案:

答案 0 :(得分:1)

char *comet,*group;
int a,b;
scanf("%s",comet);

comet指针未初始化。您需要分配内存并在此分配的内存中生成comet点,否则scanf将在随机位置写入字节,这可能会使系统崩溃。

答案 1 :(得分:1)

您永远不会为cometgroup分配空间。使用malloc() or similar为这些指针留出内存,以便您可以实际存储他们所指向的内容。

#define MAX_STRING_LENGTH 256

...

char *comet, *group;
int a, b;

comet = NULL;
comet = malloc(MAX_STRING_LENGTH);
if (!comet) {
   fprintf(stderr, "ERROR: Could not allocate memory to comet\n");
   return EXIT_FAILURE;
}
scanf("%s",comet);

/* repeat for other pointers, as needed */

/* ... */

/* free up allocated memory at the end of the program to help prevent leaks */

free(comet);
comet = NULL;

答案 2 :(得分:1)

comet和group都是未初始化的指针,没有任何内存分配用于存储输入字符串。

你的程序至少应该这样做。根据您的需要增加MAX_STRING_SIZE的大小。

#define MAX_STRING_SIZE 100
char comet[MAX_STRING_SIZE];
char group[MAX_STRING_SIZE];

使用scanf仍然存在缓冲区溢出的风险。您可以查看this帖子以了解避免缓冲区溢出的一些可能方法。

答案 3 :(得分:1)

您的while非常可疑:仅当i为大写字母时才会增加ptr[i]。如果不是,应该怎么办?如果你有一个铁板保证只会出现大写字母,你可以写:

prod = 1;
while(*ptr) {
  prod *= *ptr - 'A' + 1;
  ptr++;
}

(你的ptr[i] - '@'让我摸不着头脑,直到我爆发ascii(7)。我相信我的版本更清晰,任何中途称职的编译器都会提供相同的代码。) 或者,更具惯用性:

int cal(char *ptr)
{
    int prod = 1;

    while(*ptr)
       prod *= *ptr++ - 'A' + 1;
    return prod % 47;
}

请注意产品不会溢出,或许每个字符的模数:

int cal(char *ptr)
{
    int prod = 1;

    while(*ptr) {
       prod *= *ptr++ - 'A' + 1;
       prod %= 47;
    }
    return prod;
}

答案 4 :(得分:0)

“在我的计算机上运行良好”这在您的情况下是不可能的,因为您没有使用任何特定于编译器的代码(例如用于turbo c的getch)

你没有为存储字符串分配内存。指针彗星和组不指向任何东西.scanf需要一个地址来写入输入,但指针不包含地址,这就是为什么你得到一个分段故障。 您可以使用malloc(或calloc)分配内存,也可以定义字符数组。

更正的代码是

#include<stdio.h>
#include<string.h>
#define MAXLENGTH 100
int main()
{
    int cal(char *ptr);
    char comet[MAXLENGTH],group[MAXLENGTH];
    int a,b;
    scanf("%s",comet);
    a=cal(comet);
    scanf("%s",group);
    b=cal(group);
    if(a==b)
        printf("GO");
    else
        printf("STAY");
    return 0;
}
int cal(char *ptr)
{
    int i=0,c,prod=1,mod;
    while(ptr[i]!='\0')
    {
        if(ptr[i]>='A'&&ptr[i]<='Z')
        {
            c=ptr[i]-'@';
            prod=prod*c;
            i++;
        }
    }
    mod=prod%47;
    return mod;
}