C - Невозможно освободить выделенную память - PullRequest
0 голосов
/ 19 июля 2011

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

Проблема в следующем: большой объем сгенерированных данных (из-за избыточности) может быть отброшен вЧтобы освободить свою память.Но даже при вызове функции free () использование памяти продолжает расти.Поэтому я попытался разработать приложение для отладки, которое просто генерирует порцию данных и немедленно освобождает ее.И повторяет это тысячи раз. Ну, я не могу понять причину, но память, выделенная для процесса, увеличивается до ~ 1,8 ГБ оперативной памяти, а затем падает. Почему?Самое странное, что заставляет меня думать, что многое из того, что я не очень хорошо понимаю, это то, что когда происходит сбой процесса, malloc НЕ возвращает указатель NULL, потому что процесс всегда падает, когда readCycles == 6008, и обходит проверку NULL.

Я уже читал другие связанные с этим темы здесь, в StackOverflow, и понял, почему free () не уменьшает объем памяти, выделяемой для моего процесса.Все в порядке.Но почему использование памяти продолжает расти?Разве malloc не должен выделять ранее освобожденную память вместо того, чтобы постоянно запрашивать новую?

Это самая важная часть моего кода:

#define NREAD 1000
#define READCYCLES 10000
#define N_ALPHA_ILLUMINA 7
#define N_ALPHA_SOLID 5
#define SEQLEN 76

typedef struct{
    char* leftDNA;
    char* leftQuality;
    unsigned long int leftRow;
    char* rightDNA;
    char* rightQuality;
    unsigned long int rightRow;
} MatePair;


unsigned long int readCycles = 0;


MatePair* readStream(MatePair* inputStream, short* eof, unsigned long int* inputSize){

    double r;
    unsigned long int i, j;
    unsigned long int leftRow;
    int alphabet[] = {'A', 'C', 'G', 'T', 'N'};
    inputStream = (MatePair*) malloc (sizeof(MatePair) * (NREAD + 1));
    printf("%d\n", readCycles);
    if (inputStream == NULL){
        (*eof) = 1;
        return;
    }

    for (i = 0; i < NREAD; i++){
        leftRow = readCycles * NREAD + i;
        inputStream[i].leftDNA = (char*) malloc (SEQLEN);
        inputStream[i].rightDNA = (char*) malloc (SEQLEN);
        inputStream[i].leftQuality = (char*) malloc (SEQLEN);
        inputStream[i].rightQuality = (char*) malloc (SEQLEN);
        for (j = 0; j < SEQLEN; j++){
            r = rand() / (RAND_MAX + 1);
            inputStream[i].leftDNA[j] = alphabet[(int)(r * 5)];
            inputStream[i].rightDNA[j] = alphabet[(int)(r * 5)];
            inputStream[i].leftQuality[j] = (char) 64 + (int)(r * 60);
            inputStream[i].rightQuality[j] = (char) 64 + (int)(r * 60);
        }
        inputStream[i].leftDNA[SEQLEN - 1] = '\0';
        inputStream[i].rightDNA[SEQLEN - 1] = '\0';
        inputStream[i].leftQuality[SEQLEN - 1] = '\0';
        inputStream[i].rightQuality[SEQLEN - 1] = '\0';
        inputStream[i].leftRow = leftRow;
        inputStream[i].rightRow = leftRow;
    }

    inputStream[i].leftRow = -1;

    readCycles++;
    (*inputSize) = NREAD;
    (*eof) = readCycles > READCYCLES;

    return inputStream;

}


int main(int argc, char* argv[]){

    short eof = 0;
    unsigned long int inputSize = 0;
    MatePair* inputStream = NULL;

    while (!eof){
        inputStream = readStream(inputStream, &eof, &inputSize);
        free(inputStream);
        inputStream = NULL;
    }

    return 0;

}

Я забыл упомянуть об этом, но перед публикациейздесь вместо вызова free (inputStream) я попытался вызвать freeMemory (inputStream).Не уверен, что это правильный способ сделать это.

void freeMemory(MatePair* memblock){

    for ( ; memblock->leftRow != 1; memblock++){
        free(memblock -> leftDNA);
        free(memblock -> leftQuality);
        free(memblock -> rightDNA);
        free(memblock -> rightQuality);
    }

}

Ответы [ 2 ]

3 голосов
/ 19 июля 2011

утечки памяти. Сколько «malloc ()» вы вызвали, сколько «free ()» вы должны использовать, чтобы освободить всю выделенную память в куче.

Таким образом,

inputStream[i].leftDNA = (char*) malloc (SEQLEN);
inputStream[i].rightDNA = (char*) malloc (SEQLEN);
inputStream[i].leftQuality = (char*) malloc (SEQLEN);
inputStream[i].rightQuality = (char*) malloc (SEQLEN);

эти функции 'malloc ()' должны быть в паре с free ().

2 голосов
/ 19 июля 2011

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

Хорошо, просто посмотрите на ваши изменения, и ваша freeMemory все еще не верна.Попробуйте это;

void freeMemory(MatePair* inputStream)
{
    for (i = 0; i < NREAD; i++){
        free(inputStream[i].leftDNA);
        free(inputStream[i].leftQuality);
        free(inputStream[i].rightDNA);
        free(inputStream[i].rightQuality);
    }
    free (inputStream);
  }

Ваш free (memblock) был в цикле, чего не должно было быть, и я склонен использовать ту же итерационную последовательность при освобождении, что и mallocing.Вам также необходимо проверять ошибки после каждого malloc и решать, что делать с NULL в этой точке.

...