Условный переход или перемещение зависит от унифицированного значения - PullRequest
0 голосов
/ 17 мая 2018

Итак, valgrind дал мне эту ошибку, и я запустил ее с --track-originins = 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-originins = yes: https://pastebin.com/EyqDGBmQ Как вы можете видеть, есть много других ошибок,и я тоже не понимаю, что их вызывает.

Программа читает строки из файла с данными о температурах многих стран, я просто взял часть кода для одной страны, чтобы повторить ошибку, нострана должна быть массивом многих структур данных.Вот пример строки из файла, который я читаю:

1972-03-01,4.787,0.342, Словакия

Ответы [ 3 ]

0 голосов
/ 17 мая 2018
country = realloc(country, countries_capacity);

Вы, похоже, полагаетесь на realloc(0, new_size), чтобы вести себя как malloc(new_size). Это нормально, но тогда вы должны убедиться, что переменная-указатель, переданная в realloc, действительно равна нулю. Ни один код до этой точки не инициализирует переменную 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-строку (путем добавления нулевого терминатора), во-вторых, потому что size передан к realloc это неправильно. Вам нужно

line[line_ix] = '\0';

сразу после цикла while и

country = realloc(country, countries_capacity * sizeof(Data));

вместо realloc звонка, который у вас есть сейчас.


С этими изменениями я не получаю никаких жалоб. У вас все еще есть проблема, которую вы используете sscanf, что всегда плохая идея , но valgrind не может помочь вам с этим.

0 голосов
/ 17 мая 2018

Последний символ строки должен быть установлен в \ 0, чтобы быть правильной строкой с нулевым символом в конце.

0 голосов
/ 17 мая 2018

Проблема здесь:

country = realloc(country, countries_capacity);

country не был инициализирован, он содержит неопределенное значение.

Просто инициализируйте country до NULL после объявления следующим образом:

Data* country = NULL;
...