C 为什么这个程序分配的内存比需要的多?
我正在用C编写一个程序,需要从stdin读取。我不想让它分配超出需要的内存,所以我以块的形式读取输入,C 为什么这个程序分配的内存比需要的多?,c,malloc,C,Malloc,我正在用C编写一个程序,需要从stdin读取。我不想让它分配超出需要的内存,所以我以块的形式读取输入,malloc 下面是代码(allocd变量仅用于跟踪分配的内存量): 问题是,我的程序似乎分配的内存字节比文件中的字符多得多,如您所见: $ ./code <file.txt ALLOC'D: 1680 $。/code您正在为(尝试)读取的每一行分配新的内存块,而不管该行实际有多长。我认为,fgets是错误的工具,你想要的是: #包括 #包括 #包括 #定义尺寸20 int main(i
malloc
下面是代码(allocd
变量仅用于跟踪分配的内存量):
问题是,我的程序似乎分配的内存字节比文件中的字符多得多,如您所见:
$ ./code <file.txt
ALLOC'D: 1680
$。/code您正在为(尝试)读取的每一行分配新的内存块,而不管该行实际有多长。我认为,fgets
是错误的工具,你想要的是:
#包括
#包括
#包括
#定义尺寸20
int main(int argc,char*argv[])
{
char*str=malloc(1);
*str='\0';
焦比[SIZ];
int allocd=0;
INTP;
//注意:fread()返回读取记录的大小和数量,而不是字符*
而((p=fread(buf,1,sizeof(buf,stdin)))
{
str=realloc(str,allocd+p+1);
//连接缓冲区
memcpy(str+allocd,buf,p);
allocd+=p;
}
str[allocd+1]=0;
printf(“分配:%i”,分配);
自由基(str);
}
您正在为(尝试)读取的每一行分配一个新的内存块,而不管该行实际有多长。我认为,fgets
是错误的工具,你想要的是:
#包括
#包括
#包括
#定义尺寸20
int main(int argc,char*argv[])
{
char*str=malloc(1);
*str='\0';
焦比[SIZ];
int allocd=0;
INTP;
//注意:fread()返回读取记录的大小和数量,而不是字符*
而((p=fread(buf,1,sizeof(buf,stdin)))
{
str=realloc(str,allocd+p+1);
//连接缓冲区
memcpy(str+allocd,buf,p);
allocd+=p;
}
str[allocd+1]=0;
printf(“分配:%i”,分配);
自由基(str);
}
我正在用C编写一个程序,需要从stdin读取。我不希望它分配的内存超过所需,所以我以块的形式读取输入,每次读取一个新的块时都会占用更多的内存
好吧,对于程序员来说,您的节约意图是个好主意,但您的节约是错误的,因为您没有考虑到许多隐藏的东西,而是支持有效实现malloc
所必需的
- 首先,malloc需要将额外的内存与您请求的块相关联,以便维护堆,并且不会被分配任务搞得一团糟。这意味着,假设它与您请求的每一组内存关联的结构是一个常量,假设它是8字节大,
malloc(1)
将需要使用8bytes+1
(这是您请求的最后一个)来管理您的任务。这意味着,如果您进行了一百万次这样的分配,您将在您的责任中分配一百万字节,但您将在malloc
开销中浪费800万字节。具有活动计数的malloc数
- 第二个问题是,当您使用malloc时,您正在将用于记住malloc给您的位置的指针的大小添加到总开销中。这在最后一个地方没有考虑,因为您只能使用一个alloc来存储一个数组,在该数组中存储一百万个相邻的结构,并且只使用一个指针引用它们。但是这通常是没有用的,如果您是那些在对象之间进行引用的指针,那么您将需要在记帐中包含所有这些指针。如果我们将此开销添加到上面分配的100万字节中,您将额外增加400-800万字节的开销。这意味着您已经分配了一百万字节,但是为了维护这些字节,您需要额外的800万字节开销,并且在malloc中隐藏了800万字节的开销
- 可以避免代码中的初始
malloc(1)
。如果您阅读,您将看到realloc
不需要非空指针来操作,如果您将null
指针传递给它,它的行为将类似于初始的malloc()
调用,但需要的实际存储量是多少
代码中的方法是正确的,您一直在使用单个活动malloc,您已经决定按照SIZ
(一个大的SIZ
有助于将malloc
调用的开销降至最低,但平均而言,您将导致未使用内存的开销---分配的内存,但没有填充字符,大约是SIZ
值的一半,可能更多)由于行长应遵循毒药分布,因此SIZ
的最佳值应为平均行长(如果使用该平均值的两倍,则更好,以获得更好的性能)
一旦更正,您的代码将是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZ 60 /* assumed an average line length of 30 chars */
int main(int argc, char *argv[])
{
char *str = NULL; /* <<< use null, don't allocate something you don't need */
char buf[SIZ];
/* you don't need to know how many times you repeated the loop */
int allocd = 0; /* allocated capacity */
int strsz = 0; /* filled size */
while (fgets(buf, sizeof(buf), stdin)) /* the p pointer is not necessary */
{
/* grow str */
int read_chars = strlen(buf); /* (1 & 2) see below */
printf("read: [%s]\n", buf);
int pos_to_cp = strsz; /* (3) we need this at the end
*/
strsz += read_chars;
if (strsz >= allocd) { /* need to grow */
printf("growing from %d to %d\n", allocd, allocd + (int)sizeof buf);
allocd += sizeof buf; /* new size */
str = realloc(str, allocd); /* reallocate to allocd */
}
strcpy(str + pos_to_cp, buf); /* (3) see below */
/* (4) see below */
}
printf("ALLOC'D: %i\n", allocd);
printf("string: %s\n", str);
free(str);
}
#包括
#包括
#包括
#定义SIZ 60/*假定平均线长度为30个字符*/
int main(int argc,char*argv[])
{
char*str=NULL;/*
我正在用C编写一个程序,需要从stdin中读取数据。我不希望它分配的内存超过需要的数量,所以我正在分块读取输入,每次读取一个新的块时都会占用更多的内存
好吧,对于程序员来说,您的节约意图是个好主意,但您的节约是错误的,因为您没有考虑到许多隐藏的东西,而是支持有效实现malloc
所必需的
- 首先,malloc需要将额外的内存与您请求的块相关联,以维护堆并且不会被分配任务搞砸。这意味着,假设它与您请求的每一组内存相关联的结构是一个常量,假设它是8字节大,
malloc
$ ./code <file.txt
ALLOC'D: 1680
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZ 60 /* assumed an average line length of 30 chars */
int main(int argc, char *argv[])
{
char *str = NULL; /* <<< use null, don't allocate something you don't need */
char buf[SIZ];
/* you don't need to know how many times you repeated the loop */
int allocd = 0; /* allocated capacity */
int strsz = 0; /* filled size */
while (fgets(buf, sizeof(buf), stdin)) /* the p pointer is not necessary */
{
/* grow str */
int read_chars = strlen(buf); /* (1 & 2) see below */
printf("read: [%s]\n", buf);
int pos_to_cp = strsz; /* (3) we need this at the end
*/
strsz += read_chars;
if (strsz >= allocd) { /* need to grow */
printf("growing from %d to %d\n", allocd, allocd + (int)sizeof buf);
allocd += sizeof buf; /* new size */
str = realloc(str, allocd); /* reallocate to allocd */
}
strcpy(str + pos_to_cp, buf); /* (3) see below */
/* (4) see below */
}
printf("ALLOC'D: %i\n", allocd);
printf("string: %s\n", str);
free(str);
}