2013-11-17 6 views
0

Я не могу понять, что я сделал неправильно здесь. Новое в VALGRIND и C в целом, но удалось очистить все мои утечки MEM, кроме этого одногоОшибка утечки памяти

==8749== HEAP SUMMARY: 
==8749==  in use at exit: 880 bytes in 11 blocks 
==8749== total heap usage: 80 allocs, 69 frees, 5,620 bytes allocated 
==8749== 
==8749== 400 bytes in 5 blocks are definitely lost in loss record 1 of 2 
==8749== at 0x4C2A2DB: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==8749== by 0x402B1C: tokenize (tm_utility.c:78) 
==8749== by 0x402E57: load_data (tm_utility.c:188) 
==8749== by 0x400D0A: main (tm.c:57) 
==8749== 
==8749== 480 bytes in 6 blocks are definitely lost in loss record 2 of 2 
==8749== at 0x4C2A2DB: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==8749== by 0x402B1C: tokenize (tm_utility.c:78) 
==8749== by 0x402C97: load_data (tm_utility.c:147) 
==8749== by 0x400D0A: main (tm.c:57) 
==8749== 

Это относится к этой функции:

char** tokenize(const char* input) 
{ 
    char* str = (char*)strdup(input); 
    int count = 0; 
    int capacity = 10; 
    char** result = malloc(capacity*sizeof(*result)); /*LINE 78*/ 

    char* tok=strtok(str,","); 

    while(1) 
    { 
     if (count >= capacity) 
      result = realloc(result, (capacity*=2)*sizeof(*result)); 

     result[count++] = tok? strdup(tok) : tok; 

     if (!tok) break; 

     tok=strtok(NULL,","); 
    } 

    free(str); 
    return result; 
} 

Я могу видеть, что я не свободна» d что-то есть, но я не могу понять, где его освободить (вызов функции или локально?), и что именно я должен освободить?

Помощь?

Благодаря

EDIT:

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

while (fgets(line, sizeof(line), coinsfile_stream) != NULL) 
{ 

    tokens = tokenize(line); 

    for(i=tokens; i && *i; ++i) 
    { 

     if(y==0) 
     { 
      tm->coins[x].denomination = atoi(*i); 
      y=1; 
      x++; 
     } 
     else 
     { 
      tm->coins[z].count = atoi(*i); 
      y=0; 
      z++; 
     } 
     free(*i); 
    } 
} 
+0

Если в 'input' нет' '', то код возвращает недопустимую ссылку в качестве первого элемента, так как ему присваивается 'tok', которому были присвоены' str', а 'str' -' free() ' ed при выходе из 'tokenize'. – alk

+0

@alk true, но все входные данные содержат ',' – Chris

ответ

3

Код, который вызывает tokenize() в load_data(), кажется, отвечает за выполнение освобождение. Вы возвращаете выделенное пространство вызывающей функции.


С дополнительным кодом теперь отображается на вопрос, вам нужно добавить free(tokens); после for цикла, который обрабатывает маркеры. Этот код ниже работает с чистым законопроектом здоровья от valgrind: файл

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

char **tokenize(const char *input); 

char **tokenize(const char *input) 
{ 
    char *str = (char *)strdup(input); 
    int count = 0; 
    int capacity = 10; 
    char **result = malloc(capacity*sizeof(*result)); /*LINE 78*/ 

    char *tok = strtok(str, ",\n"); 

    while (1) 
    { 
     printf("Found: <<%s>>\n", tok); 
     if (count >= capacity) 
      result = realloc(result, (capacity *= 2)*sizeof(*result)); 

     result[count++] = tok ? strdup(tok) : tok; 

     if (!tok) 
      break; 

     tok = strtok(NULL, ",\n"); 
    } 

    free(str); 
    return result; 
} 

int main(void) 
{ 
    char line[1024]; 
    int x = 0; 
    int y = 0; 
    int z = 0; 

    struct Coin { 
     int denomination; 
     int count; 
    }; 
    struct Trade { 
     struct Coin coins[10]; 
    }; 
    struct Trade tm1; 
    struct Trade *tm = &tm1; 

    while (fgets(line, sizeof(line), stdin) != NULL) 
    { 
     char **tokens = tokenize(line); 

     for (char **i = tokens; i && *i; ++i) 
     { 
      printf("Token: <<%s>>\n", *i); 
      if (y == 0) 
      { 
       tm->coins[x].denomination = atoi(*i); 
       y = 1; 
       x++; 
      } 
      else 
      { 
       tm->coins[z].count = atoi(*i); 
       y = 0; 
       z++; 
      } 
      free(*i); 
     } 
     free(tokens); 
    } 
} 

данных:

12,23 
34,45 
56,67 

Примера вывод:

Found: <<12>> 
Found: <<23>> 
Found: <<(null)>> 
Token: <<12>> 
Token: <<23>> 
Found: <<34>> 
Found: <<45>> 
Found: <<(null)>> 
Token: <<34>> 
Token: <<45>> 
Found: <<56>> 
Found: <<67>> 
Found: <<(null)>> 
Token: <<56>> 
Token: <<67>> 

Осторожно: мой код зависит от системы I» m работает (Mac OS X 10.9 Mavericks, GCC 4.8.2 - но valgrind работает в старинной Linux VM, размещенной на той же платформе), а не сбой при запросе на печать строки, на которую указывает n ull указатель. Вам необходимо просмотреть цикл while (1); вы должны, вероятно, просто изменить его на while (tok != 0) или его эквивалент. Как только вы это сделаете, вы также можете упростить тело цикла; есть два в настоящее время избыточных теста для nullness.

+1

. Обратите внимание, что освобождение просто «результата» недостаточно. Вы также должны освободить все строки внутри 'result', так как они поступают из' strdup'. –

+0

Спасибо. Я пытался освободиться от вызывающей функции, но не могу ее получить ... вопрос обновлен. – Chris

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