我使用的是 Visual Studio 2017,我在 C 中有这段代码。当我在 VS 中运行时它失败了,但是当我用 gcc 编译时它运行完美。错误是这样的:
Exception thrown at 0x779BE643 (ntdll.dll) in GestaoFinanceira.exe: 0xC0000005: Access violation reading location 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
的原因.
最佳答案
您需要先重新分配,然后再添加新元素,而不是相反。
我不喜欢这个
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);
}
有几个原因:
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++;
不要在main
以外的函数中执行exit
。而不是关闭程序,
使 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;
}
并且错误信息应该打印到stderr
,而不是stdout
。
关于c - realloc 在 visual studio 中失败,但可以使用 gcc (ntdll.dll),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49417873/