在Visual Studio中realloc失败,但使用gcc(ntdll.dll)

时间:2018-03-21 22:59:29

标签: c visual-studio gcc malloc realloc

我使用的是Visual Studio 2017,我在C中使用了这段代码。当我在VS中运行时,它失败了,但是当我使用gcc进行编译时,它运行得很好。错误是这样的:

  

GestaoFinanceira.exe中0x779BE643(ntdll.dll)抛出异常:0xC0000005:访问冲突读取位置0x00000009。

这是我的代码。

我正在使用这种结构类型:

struct budget {
    struct tm time;
    float valor;
};

struct geral {
    struct budget *b;
    int nelem_budget;
};

在main中,我调用一个将从文件读取并保存值的函数是结构g->b[],作为g->nelem_budget

中元素的数量
int main() {
    struct geral *g = (struct geral *)malloc(sizeof(struct geral));

    readFileBudget(g);
    // just to check if the read was ok
    showBudget(g->b, g->nelem_budget);

    addBudget(g);
    // to check again if the item added is ok
    showBudget(g->b, g->nelem_budget);

    system("Pause");
    return 0;
}

以下是出现错误的时间:

void addBudget(struct geral *g) {
    int month, year;
    float value;

    // in the future, this values are to be an user input
    month = 5;
    year = 2015;
    value = 5000;

    printf("Month: %d, Year: %d, Value: %f\n", month, year, value);

    g->b[g->nelem_budget].time.tm_mon = month;
    g->b[g->nelem_budget].time.tm_year = year;
    g->b[g->nelem_budget].valor = value;

    g->nelem_budget++;

    struct budget *tmp = NULL;
    tmp = g->b;
    g->b = realloc(g->b, g->nelem_budget * sizeof(struct budget));
    if (g->b == NULL) {          //reallocated pointer ptr1
        free(tmp);
        printf("error-addBudget->realloc");
        exit(EXIT_FAILURE);
    }

    // just for debug
    printf("month: %d, year: %d, value: %f\n", g->b[g->nelem_budget - 1].time.tm_mon, g->b[g->nelem_budget - 1].time.tm_year, g->b[g->nelem_budget - 1].valor);
}

我在g->b数组的末尾有一个空值,这就是为什么我首先添加值,然后我调用realloc

1 个答案:

答案 0 :(得分:1)

您需要先重新分配,然后添加新元素,而不是反过来。

我不喜欢这个

struct budget *tmp = NULL;
    tmp = g->b;
    g->b = realloc(g->b, g->nelem_budget * sizeof(struct budget));
    if (g->b == NULL) {          //reallocated pointer ptr1
        free(tmp);
        printf("error-addBudget->realloc");
        exit(EXIT_FAILURE);
    }

有几个原因:

应该像这样调用{p> realloc

struct budget *tmp;

tmp = realloc(g->b, (g->nelem_budget + 1) * sizeof *tmp);

if(tmp == NULL)
{
    // error handling
    return 0; // return error code
}

g->b = tmp;
g->nelem_budget++;

不要在exit以外的函数中执行main。而不是关闭程序, make addBudget成功时返回1,失败时返回0。 addBudget的来电者 应该决定在失败的情况下做什么,而不是addBudget。如果你举个例子 将这些函数放在库中,程序会自动以错误结束, 而且这有时是你不想发生的事情。

因此,该函数应如下所示:

int addBudget(struct geral *g) {
    if(g == NULL)
        return 0;

    int month, year;
    float value;

    // in the future, this values are to be an user input
    month = 5;
    year = 2015;
    value = 5000;

    // reallocate first

    struct budget *tmp = NULL;
    tmp = realloc(g->b, (g->nelem_budget + 1) * sizeof *tmp);

    if(tmp == NULL)
    {
        fprintf(stderr, "error-addBudget->realloc\n");
        return 0;
    }

    g->b = tmp;

    // add new budget after reallocation
    printf("Month: %d, Year: %d, Value: %f\n", month, year, value);

    g->b[g->nelem_budget].time.tm_mon = month;
    g->b[g->nelem_budget].time.tm_year = year;
    g->b[g->nelem_budget].valor = value;

    g->nelem_budget++;

    // just for debug
    printf("month: %d, year: %d, value: %f\n", g->b[g->nelem_budget - 1].time.tm_mon, g->b[g->nelem_budget - 1].time.tm_year, g->b[g->nelem_budget - 1].valor);

    return 1;
}

然后在main

int main() {
    // using calloc to initialize
    // everything with 0
    struct geral *g = calloc(1, sizeof *g);

    if(g == NULL)
    {
        fprintf(stderr, "Not engough memory\n");
        return 1;
    }

    // you should also check of readFileBudget
    // fails
    readFileBudget(g);

    // just to check if the read was ok
    showBudget(g->b, g->nelem_budget);

    if(addBudget(g) == 0)
    {
        free(g->b);
        free(g);
        return 1;
    }

    // to check again if the item added is ok
    showBudget(g->b, g->nelem_budget);


    // don't forget to free the memory
    free(g->b);
    free(g);

    system("Pause");
    return 0;
}

另见:do not cast malloc

错误消息应打印到stderr,而不是stdout