【发布时间】:2011-07-19 10:33:39
【问题描述】:
我目前正在开发的应用程序有问题。在这个程序中,我必须从文本文件中读取大量(数十亿)数据并进行管理,但由于这是一个两个学生的项目,所以阅读部分将由我的伙伴开发。出于测试原因,我编写了一个小程序来生成伪随机结构来代替我的伙伴所做的事情。
问题如下:大量生成的数据(由于冗余)可以被丢弃以释放其内存。但即使调用 free() 函数,内存使用量也在不断增长。所以我尝试开发一个调试应用程序,它可以简单地生成一大块数据并立即释放它。并重复数千次。 好吧,我无法理解原因,但分配给进程的内存增长到 ~1.8 GB 内存然后崩溃。 为什么?最奇怪的事情是,当进程崩溃时,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);
}
}
【问题讨论】:
-
尝试为所有
malloc调用添加检查并使用valgrind 运行程序。也不是你的问题,但r = rand() / (RAND_MAX + 1)总是会是0,除非你在划分之前给double添加一个演员表。 -
这里有几个内存泄漏,分配给 inputstream[i].leftDNA 等的内存在哪里释放。
-
是的,我已经注意到(双重)的东西,忘记修改它,因为我更担心内存泄漏的事情:)
-
我建议将 DNA 序列重新编码为 char 数组(例如 char leftDNA[SEQLEN])。这样,您可以一次性分配结构数组,而不是分多个步骤进行。要完全跳过动态内存分配,请在调用 readStream() 之前在堆栈上声明结构数组,并将其传递给 readStream()。我假设您的系统不是嵌入式系统,并且可以处理大约 300 kb 的堆栈。
-
问题是 readStream() 只是一个调试存根,在最终的应用程序中,直到我读取(并处理)第一个文本文件的第一行,我才会知道 SEQLEN 中的值,据我所知,这是唯一的方法,不是吗? (我可能错了,距离我上一个 C 程序已经有好几年了,我从来都不是它的专家)
标签: c memory-management crash free