2012-06-28 4 views
4

В моей программе C, я выделение памяти с использованием malloc(), который делает, в отличии от calloc(), не инициализации памяти и все еще может содержать мусор. В основном, в контексте выделения я не делаю никаких изменений в памяти, выделенной malloc(). (Например, в функции инициализации структуры, содержащей буфер, я не вношу изменений в память буфера, но позже).Valgrind, «неинициализированное значение (s)» ошибка

Valgrind дает мне много theese ошибок:

  • Условный переход или шаг зависит от неинициализированного значения (ов)
  • Использования неинициализированного значения размера 4

I я уверен, что никогда не читал из памяти, которая не была инициализирована в этих случаях.

Должен ли я игнорировать их или лучше инициализировать память при распределении? В случае, если я должен их игнорировать, как отключить это сообщение об ошибке в Valgrind?


Пример 1:

==4253== Conditional jump or move depends on uninitialised value(s) 
==4253== at 0x408EB8E: vfprintf (vfprintf.c:1624) 
==4253== by 0x4093C2E: printf (printf.c:35) 
==4253== by 0x40624D2: (below main) (libc-start.c:226) 
==4253== Uninitialised value was created by a heap allocation 
==4253== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==4253== by 0x8048938: gk_StreamBufferNode_init (stream.c:101) 
==4253== by 0x8048D0D: gk_Stream_bufferWriteProc (stream.c:252) 
==4253== by 0x8048665: main (main.c:21) 

код:

int gk_StreamBufferNode_init(gk_StreamBufferNode* node, int buffer_size, 
          gk_AllocProc malloc) { 
    node->buffer = malloc(buffer_size);  // line 101 
    if (node->buffer == NULL) { 
     return GKIT_FAILEDALLOC; 
    } 
    node->next = NULL; 
    return GKIT_NOERR; 
} 

Пример 2:

==4253== Conditional jump or move depends on uninitialised value(s) 
==4253== at 0x402DA39: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==4253== by 0x8048C6E: gk_Stream_bufferWriteProc (stream.c:230) 
==4253== by 0x8048665: main (main.c:21) 
==4253== Uninitialised value was created by a heap allocation 
==4253== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==4253== by 0x8048CE0: gk_Stream_bufferWriteProc (stream.c:248) 
==4253== by 0x8048665: main (main.c:21) 

Код:

/* ... */ 
    int available_bytes = binfo->buffer_size - bnode->filled; 
    int bytes_to_go = size * count; 
    int offset = 0; 
    int node_offset = 0; 
    gk_StreamBufferNode* new_node; 
    void* destination = NULL; 
    void* source = NULL; 

    while (bytes_to_go > 0) { 
     destination = bnode->buffer + bnode->filled + node_offset; 
     source = buffer + offset; 
     if (available_bytes > bytes_to_go) { 
      memcpy(destination, source, bytes_to_go); // line 230 
      bnode->filled += bytes_to_go; 
      offset += bytes_to_go; 
      node_offset = bytes_to_go; 
      bytes_to_go = 0; 
     } 
     else { 
      memcpy(destination, source, available_bytes); 
      offset += available_bytes; 
      node_offset = 0; 
      bytes_to_go -= available_bytes; 
      bnode->filled += available_bytes; 

      #ifdef DEBUG 
       assert(bnode->filled == bnode->buffer_size); 
      #endif // DEBUG 

      // Allocate a new buffer node. 
      new_node = (gk_StreamBufferNode*) malloc(sizeof(gk_StreamBufferNode)); // line 248 
      if (new_node == NULL) { 
       return GKIT_FAILEDALLOC; 
      } 
      int success = gk_StreamBufferNode_init(new_node, binfo->buffer_size, 
                malloc); 
      if (success <= GKIT_ERROR) { 
       free(new_node); 
       return GKIT_FAILEDALLOC; 
      } 
      bnode->next = new_node; 
      bnode = new_node; 
      available_bytes = binfo->buffer_size; 
     } 
    } 
+1

Вы не должны игнорировать такие ошибки. Если вы разместите какой-либо код, мы можем помочь вам выявить проблему. Там где-то есть инструкция 'if', потому что в ней говорится« Условный переход ». – dasblinkenlight

+0

@Als Я добавил 2 примера. :) –

ответ

5

В обоих случаях вы просто выделяете память без ее инициализации. Самый простой способ - использовать calloc вместо malloc, чтобы обнулить его. Это может быть хорошей стратегией для простых случаев, например, если позднее вы используете buffer в качестве строки, которая должна быть напечатана. Для более сложных случаев использования присваивайте значения отдельным полям, или даже лучше, если у вас C99 назначить всю структуру из составного литерала:

toto * t = malloc(sizeof(*t));  
*t = (toto){ 0 }; 
+0

1. Как должно выполняться задание? Компилятор теперь не имеет размер блока памяти, на который указывает 't'. 2. Разве это не слишком большие накладные расходы? Я абсолютно уверен, что не читал из памяти, которая не была установлена. –

+5

@NiklasR, он знает тип '* t', поэтому это присваивание значения объекту типа' toto'. Единственные типы, для которых это не сработало, - это тип массива типа 'struct', integer или floating point, все это было бы нормально. Для прочитанного, что вы заявляете, я абсолютно уверен, что вы * * читаете единичную память где-то, если явно неявно в 'printf' или так. Обычно valgrind является надежным в своих выводах. Нет, это не большие накладные расходы, по сравнению с чтением, если из ОЗУ, например. ОЗУ на несколько порядков медленнее, чем у процессора. В любом случае, сначала сделайте это правильно, затем оптимизируйте. –

2

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

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

+1

Даже если я уверен, что я никогда не читаю из неинициализированной памяти? –

+3

Обычно, когда программа читает из неинициализированной памяти, автор уверен, что они не читают ее. Просто говорю'. – argentage

+1

@NiklasR: Вы читаете книгу из неинициализированной памяти. Первый случай может быть просто ложным положительным результатом оптимизированного 'strlen', возможно, считывающего 4 байта за раз, возможно, считывая (но игнорируя) неинициализированные байты. Вы можете их подавить, если уверены, что они действительно ложные срабатывания (см. Опции valpinds -suppressionions и '-gen-suppressionions') – Hasturkun

Смежные вопросы