由于指针分配,C程序崩溃

时间:2016-07-20 15:55:00

标签: c ansi

我正在为ANSI C书中的一个练习编写一个程序,当我到达这一行时程序崩溃了:

*pmonth = i;

在函数month_day。

#include <stdio.h>

void month_day(int year, int yearday, int *pmonth, int *pday);

int main(int argc, char *argv[]){
    int year = 1994;
    int *month;
    int yearday = 288;
    int *day;
    month_day(year, yearday, month, day);
    printf("Month = %d, day = %d", *month, *day);
    return 1;
}

static char daytab[2][14] = {
        {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
        {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

void month_day(int year, int yearday, int *pmonth, int *pday){
    int i, leap;

    leap = (year%4 == 0 && year%100 != 0) || year%400 == 0;
    char *p = &daytab[leap][1];
    for(i = 1; yearday> (int) *p; i++){
        yearday -= *p++;
    }
    *pmonth = i; /*CRASHES HERE*/
    *pday = yearday;
}

为什么会发生这种情况?我对指针比较新,所以我很容易犯一个愚蠢的错误。提前谢谢。

编辑谢谢你们的答案和耐心,试着掌握指针。

3 个答案:

答案 0 :(得分:2)

指针pmonth未初始化。所以你不应该取消引用它。您应该为指针指定一个有效的地址。为此,您可以使用&运算符分配变量地址,也可以调用malloc(1)

由于您似乎不需要主函数中的指针,因此您的代码应为:

int main(int argc, char *argv[]){
    int year = 1994;
    int month;
    int yearday = 288;
    int day;
    month_day(year, yearday, &month, &day);
    printf("Month = %d, day = %d", month, day);
    return 1;
}

在此代码中,我们向pmonthpday提供变量monthday的地址。这些变量存在于此上下文中,因此它们的地址有效。这样,pmonthpday指向有效的内存。

如果您确实需要main函数中的指针,请调用malloc(1)为程序分配内存并将该内存块的地址存储到指针中。

答案 1 :(得分:1)

这是因为您永远不会为pmonth创建任何指向的内存。您需要将任何指针指向某个内存以供其编辑,如果不这样且指针未初始化或NULL则您有未定义行为。未定义的行为意味着任何事情都可能发生,包括程序崩溃或偷车。

这样的东西就足够了:

int month; // Some actual memory.
int *pmonth = &month; // pmonth now points to something real.

但话说回来,month_day函数的要点是提供输出参数,所以即使这样就足够了:

int month, day;

month_day( ..., &month, &day)

答案 2 :(得分:0)

永远不要使用未初始化的指针或取消引用空指针,你所做的是未定义的行为,世界上任何事情都可能发生。

您已经定义了一个函数void month_day(int year, int yearday, int *pmonth, int *pday),它需要两个指向int(pmonth and pday)的指针才能传递给它。您已正确传递指向int的指针,并且编译器已成功编译您的程序,但这些指针并未指向正确的内存地址。当您访问未初始化指针指向的地址(可能无效或不属于您)时,您将获得Segmentation Fault

分段错误是一种特殊的错误,它是由访问“不属于你”的内存引起的。它是一种帮助机制,可以防止破坏内存并引入难以调试的内存错误。

有很多方法可以获得段错误。获取段错误的常用方法是取消引用空指针:

int *p = NULL;
*p = 1;

要解决您的问题,您的代码应该类似于下面的代码

int main(int argc, char *argv[])
{
    int year = 1994;
    int month;
    int yearday = 288;
    int day;

    month_day(year, yearday, &month, &day);
    printf("Month = %d, day = %d", month, day);

    return 0;
}

或者

您可以调用malloc函数动态分配内存,并将malloc函数返回的地址分配给指针变量。 Remember, to call free function to release memory allocated dynamically when you no longer need the memory