如何摆脱“中止陷阱:6”

时间:2015-09-29 18:37:18

标签: c abort

到目前为止,这是我的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv){
    char a[15],d;
    int month, day;
    char *m=&a[15];
    scanf("%s %s", m, &d); 

    if (strncmp(m,"January",7)==0) month = 1;
        else if(strncmp(m,"Febuary", 7)==0) month = 2;
        else if(strncmp(m,"March",5)==0) month = 3;
        else if(strncmp(m,"April",5)==0) month = 4;
        else if(strncmp(m,"May",3)==0) month = 5;
        else if(strncmp(m,"June",4)==0) month = 6;
        else if(strncmp(m,"July",4)==0) month = 7;
        else if(strncmp(m,"August",6)==0) month = 8;
        else if(strncmp(m,"September",9)==0) month = 9;
        else if(strncmp(m,"October",7)==0) month = 10;
        else if(strncmp(m,"November",8)==0) month = 11;
        else if(strncmp(m,"December",8)==0) month = 12;
        else {month =0; printf("invalid date");};

    day = atoi(&d);

    int months[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
    int days = months[month-1] + day;
    printf("%s %d is the %d day of the year\n",m, day, days);

    return 0;
}

所有代码都正确运行但是在程序结束时它给出了错误消息Abort trap:6。我知道这与内存分配有关,但我不知道具体是什么导致它。

编辑:旁注,对于此代码,我可以假设日期将以正确的格式输入,例如“月日”,月份始终为大写字母和实际月份等。

2 个答案:

答案 0 :(得分:3)

发生中止陷阱是因为d是单个字符,但您尝试将字符串存储到其中。 scanf能够阅读和转换数字,因此您可以取消datoi,只需使用scanf直接阅读这一天。

我还应该指出行

char *m=&a[15];

m指向数组的结尾。如果消除a并将m声明为数组,则m可用作指向数组开头的指针。

代码的前几行应该如下所示

int main(int argc, char **argv){
    char m[16];
    int month, day;
    scanf("%15s%d", m, &day); 

    if (strcmp(m,"January")==0) month = 1;

附注:使用strncmp是不必要的(因为m和常量字符串都很好)并且容易出错(因为你可能会得到错误的长度)。因此,应使用strcmp进行比较。

正如@JonathanLeffler在评论中指出的那样,使用strncmp将允许无效的月份名称通过比较。例如,

strncmp( "Maybe", "May", 3 )

将返回0。

答案 1 :(得分:2)

首先,我尝试在我的Linux机器上运行你的代码并没有问题,但是如果我输入无效的日期,我得到一个与堆栈粉碎有关的错误,我相信你正在经历的。 正如雷蒙德指出的那样,以下几行确实是错误的。

    char *m=&a[15];

我可能会犯错,但我相信这说,从[15](无效内存)中获取值并获取该地址,然后将其存储为m。基本上,你会在数组a结束后立即获得指向地址的指针。因此,当您在m中存储某些内容时,这不是您要求操作系统导致意外行为的内存。我建议您将该行更改为以下内容,因为它可以更好地为您工作。

char m[15];