条件跳转或移动取决于未初始化的值
Conditional Jump or move depends on unitialised value
所以,valgrind 给了我那个错误,我用 --track-origins=yes 运行 它并找到了错误所在的行,但我不明白错误是什么或如何解决修理它。
#include <stdio.h>
#include <stdlib.h>
typedef struct Date{
int year;
int month;
int day;
} Date;
typedef struct Data{
Date date;
float temp;
float uncertainty;
char country[100];
} Data;
int main(){
FILE* f = fopen("tempcountries_short.csv", "r");
char* line = NULL;
int capacity = 0;
int countries_capacity = 0;
int line_ix = 0;
char c;
Data* country = NULL;
while ((c = fgetc(f)) != '\n'){
if (line_ix + 1 > capacity){
if (capacity == 0)
capacity = 10;
else
capacity = capacity * 2;
line = realloc(line, capacity);
}
line[line_ix] = c;
line_ix++;
}
if (countries_capacity == 0)
countries_capacity = 10;
else
countries_capacity = countries_capacity * 2;
country = realloc(country, countries_capacity);
printf("%i\n",sscanf(line, "%i - %i - %i, %f , %f , %s",
&country->date.year, &country->date.month,
&country->date.day, &country->temp, &country->uncertainty,
country->country));
}
这是 Valgrind 的输出,带有选项 --leak-check=full 和 --track-origins=yes: https://pastebin.com/EyqDGBmQ 正如你所看到的,还有很多其他错误,我没有了解导致它们的原因。
该程序正在从包含多个国家/地区温度数据的文件中读取行,我只是使用了单个国家/地区的代码部分来复制错误,但国家/地区应该是许多数据结构的数组。这是我正在阅读的文件中的示例行:
1972-03-01,4.787,0.342,斯洛伐克
问题出在这里:
country = realloc(country, countries_capacity);
country
尚未初始化,它包含一个不确定的值。
只需在声明时将 country
初始化为 NULL
:
Data* country = NULL;
country = realloc(country, countries_capacity);
您似乎依赖 realloc(0, new_size)
表现得像 malloc(new_size)
。这很好,但是您必须确保传递给 realloc
的指针变量确实为 null。在这一点之前没有代码初始化 country
变量,并且在其声明中 ...
Data* country;
...没有初始化程序。将其更改为
Data *country = 0;
这部分问题应该会消失。
通常,当您从 valgrind
收到一整串错误时,只有第一个有意义,因此请查看是否能解决所有问题。
编辑:随着程序版本的上述更正,输入显示的示例行,我没有收到关于 realloc
内未初始化值的任何投诉,但我仍然收到关于sscanf
:
中未初始化的值
==28542== Conditional jump or move depends on uninitialised value(s)
==28542== at 0x4C340E6: rawmemchr (vg_replace_strmem.c:1409)
==28542== by 0x4EB6291: _IO_str_init_static_internal (strops.c:41)
==28542== by 0x4EA476C: __isoc99_vsscanf (isoc99_vsscanf.c:41)
==28542== by 0x4EA46D3: __isoc99_sscanf (isoc99_sscanf.c:31)
==28542== by 0x108886: main (in /tmp/a.out)
以及关于无效写入的投诉:
==28542== Invalid write of size 4
==28542== at 0x4E98FFB: _IO_vfscanf (vfscanf.c:1898)
==28542== by 0x4EA4781: __isoc99_vsscanf (isoc99_vsscanf.c:43)
==28542== by 0x4EA46D3: __isoc99_sscanf (isoc99_sscanf.c:31)
==28542== by 0x108886: main (in /tmp/a.out)
==28542== Address 0x51f41a8 is 8 bytes inside a block of size 10 alloc'd
==28542== at 0x4C2CABF: malloc (vg_replace_malloc.c:298)
==28542== by 0x4C2EE04: realloc (vg_replace_malloc.c:785)
==28542== by 0x10883C: main (in /tmp/a.out)
这些都是由真正的错误引起的:第一个是因为 line
数组从未被制成正确的 C 字符串(通过添加 nul 终止符),第二个是因为 size 传递给 realloc
是错误的。你需要
line[line_ix] = '[=15=]';
紧接在 while
循环之后,并且
country = realloc(country, countries_capacity * sizeof(Data));
而不是现在的 realloc
呼叫。
通过这些更改,我没有收到 valgrind 的投诉。您仍然遇到使用 sscanf
的问题,即 always a bad idea,但 valgrind 无法帮助您。
行的最后一个字符必须设置为 \0,才能成为正确的空终止字符串。
所以,valgrind 给了我那个错误,我用 --track-origins=yes 运行 它并找到了错误所在的行,但我不明白错误是什么或如何解决修理它。
#include <stdio.h>
#include <stdlib.h>
typedef struct Date{
int year;
int month;
int day;
} Date;
typedef struct Data{
Date date;
float temp;
float uncertainty;
char country[100];
} Data;
int main(){
FILE* f = fopen("tempcountries_short.csv", "r");
char* line = NULL;
int capacity = 0;
int countries_capacity = 0;
int line_ix = 0;
char c;
Data* country = NULL;
while ((c = fgetc(f)) != '\n'){
if (line_ix + 1 > capacity){
if (capacity == 0)
capacity = 10;
else
capacity = capacity * 2;
line = realloc(line, capacity);
}
line[line_ix] = c;
line_ix++;
}
if (countries_capacity == 0)
countries_capacity = 10;
else
countries_capacity = countries_capacity * 2;
country = realloc(country, countries_capacity);
printf("%i\n",sscanf(line, "%i - %i - %i, %f , %f , %s",
&country->date.year, &country->date.month,
&country->date.day, &country->temp, &country->uncertainty,
country->country));
}
这是 Valgrind 的输出,带有选项 --leak-check=full 和 --track-origins=yes: https://pastebin.com/EyqDGBmQ 正如你所看到的,还有很多其他错误,我没有了解导致它们的原因。
该程序正在从包含多个国家/地区温度数据的文件中读取行,我只是使用了单个国家/地区的代码部分来复制错误,但国家/地区应该是许多数据结构的数组。这是我正在阅读的文件中的示例行:
1972-03-01,4.787,0.342,斯洛伐克
问题出在这里:
country = realloc(country, countries_capacity);
country
尚未初始化,它包含一个不确定的值。
只需在声明时将 country
初始化为 NULL
:
Data* country = NULL;
country = realloc(country, countries_capacity);
您似乎依赖 realloc(0, new_size)
表现得像 malloc(new_size)
。这很好,但是您必须确保传递给 realloc
的指针变量确实为 null。在这一点之前没有代码初始化 country
变量,并且在其声明中 ...
Data* country;
...没有初始化程序。将其更改为
Data *country = 0;
这部分问题应该会消失。
通常,当您从 valgrind
收到一整串错误时,只有第一个有意义,因此请查看是否能解决所有问题。
编辑:随着程序版本的上述更正,输入显示的示例行,我没有收到关于 realloc
内未初始化值的任何投诉,但我仍然收到关于sscanf
:
==28542== Conditional jump or move depends on uninitialised value(s)
==28542== at 0x4C340E6: rawmemchr (vg_replace_strmem.c:1409)
==28542== by 0x4EB6291: _IO_str_init_static_internal (strops.c:41)
==28542== by 0x4EA476C: __isoc99_vsscanf (isoc99_vsscanf.c:41)
==28542== by 0x4EA46D3: __isoc99_sscanf (isoc99_sscanf.c:31)
==28542== by 0x108886: main (in /tmp/a.out)
以及关于无效写入的投诉:
==28542== Invalid write of size 4
==28542== at 0x4E98FFB: _IO_vfscanf (vfscanf.c:1898)
==28542== by 0x4EA4781: __isoc99_vsscanf (isoc99_vsscanf.c:43)
==28542== by 0x4EA46D3: __isoc99_sscanf (isoc99_sscanf.c:31)
==28542== by 0x108886: main (in /tmp/a.out)
==28542== Address 0x51f41a8 is 8 bytes inside a block of size 10 alloc'd
==28542== at 0x4C2CABF: malloc (vg_replace_malloc.c:298)
==28542== by 0x4C2EE04: realloc (vg_replace_malloc.c:785)
==28542== by 0x10883C: main (in /tmp/a.out)
这些都是由真正的错误引起的:第一个是因为 line
数组从未被制成正确的 C 字符串(通过添加 nul 终止符),第二个是因为 size 传递给 realloc
是错误的。你需要
line[line_ix] = '[=15=]';
紧接在 while
循环之后,并且
country = realloc(country, countries_capacity * sizeof(Data));
而不是现在的 realloc
呼叫。
通过这些更改,我没有收到 valgrind 的投诉。您仍然遇到使用 sscanf
的问题,即 always a bad idea,但 valgrind 无法帮助您。
行的最后一个字符必须设置为 \0,才能成为正确的空终止字符串。