2016-04-07 3 views
-2

У меня возник вопрос о освобождении памяти, которую я выделил для массива struct в c.Чтобы освободить выделенную память для массива struct в c

У меня есть вопросы, которые были опубликованы, и ничто не прояснило мою проблему.

Прежде всего, я создал пару структур заранее; переменные внутри структуры имеют фиксированный размер, например char str[250] или int.

Я создал пару указателей на структуру и использовал malloc, чтобы превратить его как массив структуры.

Но когда я пытался освободить эти массивы структуры, он по какой-то причине не освободится.

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

Ниже приведен фрагмент кода, который похож на мою структуру; метод моего malloc в моем массиве struct; и метод моей свободной памяти.

struct word{ 
    char word[250]; 
    int occurrence; }; 

struct same_word{ 
    char word[250];}; 

int main(int argc, char** agrv){ 
    FILE* fp; 
    fp = fopen(argv[1],"r"); 
    if(fp == NULL) 
    { 
     perror("File does not open."); 
     exit(0); 
    } 

    int total_number_of_word = /*number of word I have in my txt file*/ 
    int total_number_of_same_word = /*number of same word I have in my txt file*/ 
    /* Assuming I knew these two numbers in advance*/ 

    struct word* essay = malloc(total_number_of_word * sizeof(struct word)); 
    struct same_word* unique_word = malloc(total_number_of_same_word * sizeof(struct same_word)); 

    int index = 0; 
    int index2 = 0; 
    int ret = 0; 
    while(index < total_number_of_word){ 
      fscanf(fp,"%s",essay[index].word); 
      essay[index].occurrence = 1; 
      ret = strcmp(essay[index].word,"Hello"); 
      if(ret == 0) 
      { 
       strcpy(unique_word[index2].word,essay[index].word); 
       index2++; 
      } 
      index++; 
    } 
    free(essay); 
    free(unique_word); 
    fclose(fp); 

}

Спасибо заранее.

P.S Спасибо всем, кто указал на ошибки, которые у меня есть в моем вопросе.

+1

Является ли это минимальным, полным, проверяемым примером? (Я думаю, нет, поскольку это бесконечный цикл) – immibis

+0

Seconding immibis; если вы хотите добавить только «i ++» внутри цикла while, это определенно выглядит так, как будто оно должно работать. Попробуйте сделать минимальный пример, с которым вы можете скомпилировать и запустить и увидеть то же поведение. –

+0

вы проверяете shoud, если указатель на выделенную память не равен NULL. Кроме того, если вы измените значение указателя в цикле, например, эссе ++, вы не сможете освободить его. – qleguennec

ответ

0

С минимальными изменениями в коде:

  1. agrv изменено на argv.
  2. Тест argc перед использованием argv[1], выход и сообщение об ошибке.
  3. Результат теста от scanf() и выход, если нет 1.
  4. Установка количества слов до 1000 штук.
  5. Утверждение, что выделение памяти выполнено успешно (так же, используя #include <assert.h>).
  6. Закрытие файла.
  7. Добавление возврата 0 в конец.

код составлен и запущен чисто под valgrind на Mac OS X 10.11.4 El Capitan.

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

struct word 
{ 
    char word[250]; 
    int occurrence; 
}; 

struct same_word 
{ 
    char word[250]; 
}; 

int main(int argc, char **argv) 
{ 
    if (argc != 2) 
    { 
     fprintf(stderr, "Usage: %s file\n", argv[0]); 
     return 1; 
    } 
    FILE *fp = fopen(argv[1], "r"); 
    if (fp == NULL) 
    { 
     perror("File does not open."); 
     return 1; 
    } 

    int total_number_of_word = 1000; 
    int total_number_of_same_word = 1000; 

    struct word *essay = malloc(total_number_of_word * sizeof(struct word)); 
    struct same_word *unique_word = malloc(total_number_of_same_word * sizeof(struct same_word)); 
    assert(essay != 0); 
    assert(unique_word != 0); 

    int index = 0; 
    int index2 = 0; 
    int ret = 0; 
    while (index < total_number_of_word) 
    { 
     if (fscanf(fp, "%s", essay[index].word) != 1) 
      break; 
     essay[index].occurrence = 1; 
     ret = strcmp(essay[index].word, "Hello"); 
     if (ret == 0) 
     { 
      strcpy(unique_word[index2].word, essay[index].word); 
      index2++; 
     } 
     index++; 
    } 
    fclose(fp); 
    free(essay); 
    free(unique_word); 
    return 0; 
} 

Пример запуска (название программы wd; исходный код wd.c):

$ make wd && valgrind wd wd.c 
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -Werror wd.c -o wd 
==24802== Memcheck, a memory error detector 
==24802== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. 
==24802== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info 
==24802== Command: wd wd.c 
==24802== 
==24802== 
==24802== HEAP SUMMARY: 
==24802==  in use at exit: 22,233 bytes in 186 blocks 
==24802== total heap usage: 273 allocs, 87 frees, 538,561 bytes allocated 
==24802== 
==24802== LEAK SUMMARY: 
==24802== definitely lost: 0 bytes in 0 blocks 
==24802== indirectly lost: 0 bytes in 0 blocks 
==24802==  possibly lost: 0 bytes in 0 blocks 
==24802== still reachable: 0 bytes in 0 blocks 
==24802==   suppressed: 22,233 bytes in 186 blocks 
==24802== 
==24802== For counts of detected and suppressed errors, rerun with: -v 
==24802== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 18 from 18) 
$ 

Большое количество памяти 'в использовании на выходе' и 'подавленной' нормально на Mac OS X.

Если вы столкнулись с проблемами, один из правдоподобных источников проблем состоит в том, что вы не выделили достаточно места в двух массивах. Вы действительно должны убедиться, что значения index и index2 находятся в пределах границ. Вероятно, вы могли бы позволить уменьшить длину слова - 250 довольно длинный; Вместо этого я мог бы использовать 64.Затем вы должны использовать %63s в строке формата scanf(), чтобы предотвратить переполнение (или используйте %249s с текущими структурами). В исходном коде всего 136 слов и 1241 символ. Самые длинные слова - 32 символа (malloc(total_number_of_same_word - один из них, другой - strcpy(unique_word[index2].word,).

+0

Спасибо за ответ, я никогда не знаю, что я мог бы использовать% 249s, чтобы предотвратить переполнение моей переменной. Мне удалось освободить часть моего массива struct, освободив его сразу после того, как он мне не нужен, а не освободил его в конце программы. Но у меня все еще есть некоторые массивы структуры, которые до сих пор не могут освободиться, когда я пытаюсь освободить ее после того, как я их использовал. В то же время я узнал, что valgrind сообщил мне, что мой указатель FILE * по-прежнему доступен, даже если у меня есть fclose(), чтобы закрыть txt-файл. – Ming

+0

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

0

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

Так как я делаю групповую работу с четырьмя другими людьми. Поэтому код трогает 4 разных руки, один из наших помощников по группе создал оператор if, который закончит программу правильно, вернемся к 0.

Но она забыла выпустить всю память кучи, которую мы создавали malloc() не комментирует ни один из ее кодов. Поэтому я не поймал эту глупую проблему правильно.

Я собираюсь опубликовать НЕПРАВИЛЬНЫЙ код, который у нас есть, и код CORRECT, который у нас есть прямо сейчас, для тех, кто может получить тот же глупый вопрос, что и мы.

Это неправильная версия нашего кода

struct word{ 
     char word[250]; 
     int occurrence; }; 

    struct same_word{ 
     char word[250];}; 

    int main(int argc, char** agrv){ 
     FILE* fp; 
     fp = fopen(argv[1],"r");//argv[1] is the location where we put the txt file name 
     if(fp == NULL) 
     { 
      perror("File does not open."); 
      exit(0); 
     } 

     int total_number_of_word = /*number of word I have in my txt file*/ 
     int total_number_of_same_word = /*number of same word I have in my txt file*/ 
     /* Assuming I knew these two numbers in advance*/ 

     struct word* essay = malloc(total_number_of_word * sizeof(struct word)); 
     struct same_word* unique_word = malloc(total_number_of_same_word * sizeof(struct same_word)); 

     int index = 0; 
     int index2 = 0; 
     int ret = 0; 
     while(index < total_number_of_word){ 
       fscanf(fp,"%s",essay[index].word); 
       essay[index].occurrence = 1; 
       ret = strcmp(essay[index].word,"Hello"); 
       if(ret == 0) 
       { 
        strcpy(unique_word[index2].word,essay[index].word); 
        index2++; 
       } 
       index++; 
     } 
     //... 
     if(/*a event is true*/) 
     { 
       /*she has forgot to free memory before the return 0 
       therefore we have been continuously leaking memory*/ 
       return 0; 
     } 
     //... 
     free(essay); 
     free(unique_word); 
     fclose(fp); 
     return 0; 
    } 

Ниже корректная версия кода из

struct word{ 
    char word[250]; 
    int occurrence; 
}; 

struct same_word{ 
    char word[250]; 
}; 

int main(int argc, char** agrv){ 
    FILE* fp; 
    fp = fopen(argv[1],"r");//argv[1] is the location where we put the txt file name 
    if(fp == NULL) 
    { 
     perror("File does not open."); 
     exit(0); 
    } 

    int total_number_of_word = /*number of word I have in my txt file*/ 
    int total_number_of_same_word = /*number of same word I have in my txt file*/ 
    /* Assuming I knew these two numbers in advance*/ 

    struct word* essay = malloc(total_number_of_word * sizeof(struct word)); 
    struct same_word* unique_word = malloc(total_number_of_same_word * sizeof(struct same_word)); 

    int index = 0; 
    int index2 = 0; 
    int ret = 0; 
    while(index < total_number_of_word){ 
      fscanf(fp,"%s",essay[index].word); 
      essay[index].occurrence = 1; 
      ret = strcmp(essay[index].word,"Hello"); 
      if(ret == 0) 
      { 
       strcpy(unique_word[index2].word,essay[index].word); 
       index2++; 
      } 
      index++; 
    } 
    //... 
    if(/* a event is true*/) 
    { 
      free(essay); 
      free(unique_word); 
      fclose(fp); 
      /* After freeing memory in here, we no longer have any memory leak*/ 
      return 0; 
    } 
    //... 
    free(essay); 
    free(unique_word); 
    fclose(fp); 
    return 0; 
} 

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

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

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