Где находится неинициализированное значение в этой функции? - PullRequest
2 голосов
/ 24 декабря 2011

Я запускаю отладочную версию моего двоичного файла C внутри valgrind, которая возвращает многочисленные ошибки вида Conditional jump or move depends on uninitialised value(s).

Используя таблицу символов, valgrind говорит мне, где искатьмоя программа для этой проблемы:

==23899== 11 errors in context 72 of 72:                                                                                                                                                                                                     
==23899== Conditional jump or move depends on uninitialised value(s)                                                                                                                                                                         
==23899==    at 0x438BB0: _int_free (in /foo/bar/baz)                                                                                                                         
==23899==    by 0x43CF75: free (in /foo/bar/baz)                                                                                                                              
==23899==    by 0x4179E1: json_tokener_parse_ex (json_tokener.c:593)                                                                                                                                                                         
==23899==    by 0x418DC8: json_tokener_parse (json_tokener.c:108)                                                                                                                                                                            
==23899==    by 0x40122D: readJSONMetadataHeader (metadataHelpers.h:345)                                                                                                                                                               
==23899==    by 0x4019CB: main (baz.c:90)

У меня есть следующая функция readJSONMetadataHeader(...), которая вызывает json_tokener_parse():

int readJSONMetadataHeader(...) {                                                                                                                                                                                                                                                                                                                                                                 
    char buffer[METADATA_MAX_SIZE];
    json_object *metadataJSON;
    int charCnt = 0; 
    ...
    /* fill up the `buffer` variable here; basically a */
    /* stream of characters representing JSON data...  */
    ...
    /* terminate `buffer` */
    buffer[charCnt - 1] = '\0';
    ...
    metadataJSON = json_tokener_parse(buffer);
    ...
}

Функция json_tokener_parse(), в свою очередь, выглядит следующим образом:

struct json_object* json_tokener_parse(const char *str)                                                                                                                                                                                      
{                                                                                                                                                                                                                                            
    struct json_tokener* tok;                                                                                                                                                                                                                  
    struct json_object* obj;                                                                                                                                                                                                                   

    tok = json_tokener_new();                                                                                                                                                                                                                  
    obj = json_tokener_parse_ex(tok, str, -1);                                                                                                                                                                                                 
    if(tok->err != json_tokener_success)                                                                                                                                                                                                       
        obj = (struct json_object*)error_ptr(-tok->err);                                                                                                                                                                                         
    json_tokener_free(tok);                                                                                                                                                                                                                    
    return obj;                                                                                                                                                                                                                                
}

После трассировки обратно к readJSONMetadataHeader() создается впечатление, что неинициализированное значение - это char [] (или const char *) переменная buffer, которая подается на json_tokener_parse(), что, в свою очередь, равноподается на json_tokener_parse_ex().

Но переменная buffer заполняется данными и затем завершается до вызова функции json_tokener_parse().

Так почему valgrind говорит, что это значениенеинициализированный?Чего мне не хватает?

Ответы [ 4 ]

2 голосов
/ 27 декабря 2011

Из отчета об ошибке valgrind выглядит так, как будто ваше приложение статически связано (в частности, free выглядит в основном исполняемом файле, а не libc.so.6).

Valgrind будет сообщать о поддельных ошибках для статически связанных приложений.

Точнее, в libc есть преднамеренные ошибки "не волнует". При динамическом связывании приложения такие ошибки подавляются по умолчанию (через файл подавлений, который поставляется вместе с Valgrind).

Но когда вы статически связываете свое приложение, Valgrind не имеет ни малейшего представления о том, что неисправный код поступил из libc.a, и поэтому сообщает о них.

Как правило, статическое связывание приложений в Linux - плохая идея (TM).

Запуск такого приложения под Valgrind: вдвойне: Valgrind не сможет перехватывать malloc/free вызовы и будет эффективно перехватывать только считываний неинициализированной памяти и не переполнения буфера кучи (или другие ошибки в куче), в которых он обычно хорош.

2 голосов
/ 24 декабря 2011

Я не вижу, charCnt инициализирован.

Чтобы увидеть, приходит ли он от buffer, просто инициализируйте его с = {0}, это также сделает ваше нулевое завершение буфера устаревшим.1006 *

1 голос
/ 24 декабря 2011
 buffer[charCnt - 1] = '\0';

Это по крайней мере завершится неудачей, если значение charCnt равно нулю.

1 голос
/ 24 декабря 2011

Посмотрите на json_tokener_parse_ex(), который вы не показываете.Вероятно, он пытается освободить то, что не инициализировано.

...