繁体   English   中英

在 c 中释放为结构数组分配的内存

[英]To free memory allocated for an array of struct in c

我有一个关于释放我为 c 中的结构数组分配的内存的问题。

我搜索了发布的问题,但没有任何内容可以澄清我的问题。

首先,我事先创建了几个结构; struct 内的变量都是固定大小的,例如char str[250]int

我创建了几个结构指针并使用 malloc 将其转换为结构数组。

但是当我试图释放这些结构数组时,由于某种原因它不会释放。

当我通过 valgrind 检查内存泄漏时,它告诉我无法释放内存,我肯定会丢失这些结构数组上的内存。

下面是一段与我的结构相似的代码; 我的 malloc 在我的结构数组上的方法; 以及我自由记忆的方法。

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);

}

提前致谢。

PS 感谢大家指出我在问题中的错误。

对代码进行最少的更改:

  1. agrv更改为argv
  2. 在使用argv[1]之前测试argc ,退出并报告失败。
  3. scanf()测试结果,当它不是1时退出。
  4. 将单词数设置为每个单词 1000。
  5. 断言内存分配成功(因此也使用#include <assert.h> )。
  6. 关闭文件。
  7. 最后添加 return 0。

代码在 Mac OS X 10.11.4 El Capitan 上的valgrind下编译并运行干净。

#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 上,“退出时正在使用”和“被抑制”的大量内存是正常的。

如果您遇到问题,那么一个可能的问题来源是您没有在两个数组中分配足够的空间。 您应该真正检查indexindex2的值是否在范围内。 你可能有能力减少一个词的长度——250 是相当长的; 我可能会改用 64。 那么你应该使用%63sscanf()格式字符串,以防止溢出(或使用%249s与当前的结构)。 源代码只有136个字,1241个字符。 最长的“单词”是每个 32 个字符( malloc(total_number_of_same_word是其中之一;另一个是strcpy(unique_word[index2].word, )。

感谢您的所有帮助,经过数小时的检查数千行代码后,我终于找到了程序中的问题所在。

因为我正在和另外 4 个人一起做小组工作。 因此,代码被 4 只不同的手接触,我们的一位队友创建了一个 if 语句,该语句将通过返回 0 直接结束程序。

但是她忘记释放我们通过 malloc() 创建的所有堆内存,也没有评论她的任何代码。 所以我没有立即发现这个愚蠢的问题。

我将发布我们之前拥有的错误代码和我们现在拥有的正确代码,以供可能遇到与我们一样愚蠢问题的人。

这是我们代码的错误版本

    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;
}

再次感谢大家的帮助。 由于我不经常在这个平台上提问,我不知道提问的完美方式。 我很抱歉没有在第一时间创建一个最小的、完整的、可验证的示例。

但是感谢您指出这一点,下次我提出问题时我会尝试做得更好。 我非常感谢所有的解释和建议。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM