我使用的是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
。
答案 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;
}
错误消息应打印到stderr
,而不是stdout
。