释放C中的动态字符串/行数组

时间:2015-06-15 18:28:20

标签: c string sorting malloc free

我正在编写一个程序,用于对输入文本文件中的行进行排序。它完成了它的工作,但是我使用valgrind得到了内存泄漏。

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

char* getline(FILE * infile)
{
    int size = 1024;
    char * line = (char*)malloc(size);
    int temp;

    int i=0;
    do
    {
        (temp = fgetc(infile));
        if (temp !=EOF)
            line[i++]=(char)temp;
        if (i>=size)    
        {
            size*=2;
            line = (char*)realloc(line, size);
        }

    }while (temp != '\n' && temp !=EOF);
    if (temp==EOF)
        return NULL;
    return line;
}

void print_line (char * line)
{
    printf("%s", line);
}

int myCompare (const void * a, const void * b )
{
    const char *pa = *(const char**)a;
    const char *pb = *(const char**)b;

    return strcmp(pa,pb);
}

int main (int argc, char* argv[])
{
    FILE * infile;
    FILE * outfile;

    infile = fopen(argv[1], "r");
    if (infile==NULL)
    {
        printf("Error");
        exit(3);
    }
    outfile = fopen(argv[2], "w");
    if (outfile==NULL)
    {
        printf("Error");
        exit(3);
    }
    char * line;
    char **all_lines;
    int nlines=0;

    while((line=getline(infile))!=NULL)
    {
        print_line(line);
        nlines++;
    }

    all_lines=malloc(nlines*sizeof(char*));
    rewind(infile);
    int j=0;
    printf("%d\n\n", nlines);

    while((line=getline(infile))!=NULL)
    {

        all_lines[j]=line;
        j++;
    }

    qsort(all_lines, nlines, sizeof(char*), myCompare);

    for (int i=0; i<nlines;i++)
    {
        print_line(all_lines[i]);
        fprintf(outfile, "%s", all_lines[i]);
    }

    for(int i =0; i<nlines;i++)
    {
        free(all_lines[i]);
    }

    free(all_lines);
    fclose(infile);
    fclose(outfile);
    return 0;   
}

他们可能来自哪些想法?我遍历all_lines []并释放内容,然后释放all_lines本身。

更新:

好的,我已经完成了你建议的更新。但是,现在valgrind在我的程序中抛出函数fprintf的错误。以下是它的说法:

11 errors in context 2 of 2:

==3646== Conditional jump or move depends on uninitialised value(s)
==3646==    at 0x40BA4B1: vfprintf (vfprintf.c:1601)
==3646==    by 0x40C0F7F: printf (printf.c:35)
==3646==    by 0x80487B8: print_line (sort_lines.c:44)
==3646==    by 0x804887D: main (sort_lines.c:77)
==3646==  Uninitialised value was created by a heap allocation
==3646==    at 0x4024D12: realloc (vg_replace_malloc.c:476)
==3646==    by 0x8048766: getline (sort_lines.c:30)
==3646==    by 0x804889A: main (sort_lines.c:75)

我想知道为什么它只是简单地将这些行报告给文本文件。我已经抬头看到这是关于gcc优化的问题,将fprint转化为fput但我不明白这个想法

1 个答案:

答案 0 :(得分:1)

您的代码中存在多个问题:

功能getline

  • line缓冲区中的字符串在'\0'循环结束时未正确do / while终止。
  • 文件末尾没有free line缓冲区,因此内存泄漏
  • 如果文件未以'\n'结尾,则不会在文件末尾返回部分行。
  • 检查malloc而不是realloc返回值是否存在内存分配失败。
  • 您应该realloc line到用于减少内存消耗量的实际大小。目前,每行至少分配1024个字节。对字典进行排序将需要 100倍更多的内存!

功能MyCompare

读取的行包括最后的'\n'。比较可能会产生意外结果:"Hello\tworld\n"将在"Hello\n"之前出现。您应该删除'\n'中的getline并正确修改printf格式。

功能main

  • 在尝试使用fopen打开命令行参数之前,不检查是否实际提供了命令行参数,从而调用未定义的行为
  • 计算行数的第一个循环不free getline返回的行... 大内存泄漏
  • 输入流不能始终为rewind。如果您的程序通过管道输入,rewind将失败,除非输入尺寸非常小。
  • 如果文件是由另一个进程异步修改的,则第二个循环中读取的行数可能与第一个循环中计算的行数不同。文件增长,加载时调用未定义的行为,如果收缩,则在对数组进行排序时调用未定义的行为。在单循环中读取行时,应重新分配all_lines数组。

在排序之前打印线条不是很有用,并使测试复杂化。