如何继续使用 malloc?
how to keep using malloc?
我有一个存储整数序列的文件。整数总数是未知的,所以如果我从文件中读取整数,我会继续使用 malloc() 来申请新内存。
我不知道我是否可以继续请求内存并将它们添加到数组的末尾。 Xcode 一直警告我 malloc() 行中的 'EXC_BAD_EXCESS'。
如果我一直从文件中读取整数,我该怎么做?
int main()
{
//1.read from file
int *a = NULL;
int size=0;
//char ch;
FILE *in;
//open file
if ( (in=fopen("/Users/NUO/Desktop/in.text","r")) == NULL){
printf("cannot open input file\n");
exit(0); //if file open fail, stop the program
}
while( ! feof(in) ){
a = (int *)malloc(sizeof(int));
fscanf(in,"%d", &a[size] );;
printf("a[i]=%d\n",a[size]);
size++;
}
fclose(in);
return 0;
}
- 不使用
malloc
,而是使用 realloc
。
- 不要在
while
循环中使用 feof(in)
。 See why.
int number;
while( fscanf(in, "%d", &number) == 1 ){
a = realloc(a, sizeof(int)*(size+1));
if ( a == NULL )
{
// Problem.
exit(0);
}
a[size] = number;
printf("a[i]=%d\n", a[size]);
size++;
}
像那样反复调用 malloc()
并不像您认为的那样。每次调用 malloc(sizeof(int))
时,它都会分配一个单独的新内存块,该内存块只够容纳一个整数。写入 a[size]
最终会为第一个值之后的每个值注销该数组的末尾。
这里你要的是realloc()
函数,例如
a = realloc(a, sizeof(int) * (size + 1));
if (a == NULL) { ... handle error ... }
修改您的代码,使 size
实际上是数组的 大小 ,而不是它的最后一个索引,这将有助于简化此代码,但这既不是这里也不是那里。
您还没有分配一个整数数组,您在这里分配了一个整数。因此,您需要分配默认数组大小,然后在即将超过 运行 时调整大小。这将在每次填满时将其大小调整 2。以这种方式调整大小可能不符合您的最佳利益,但您也可以为每个附加字段重新分配每个字段。
size_t size = 0;
size_t current_size = 2;
a = (int *)malloc(sizeof(int) * current_size);
if(!a)
handle_error();
while( ! feof(in) ){
if(size >= current_size) {
current_size *= 2;
a = (int *)realloc(a, sizeof(int) * current_size);
if(!a)
handle_error();
}
fscanf(in,"%d", &a[size] );;
printf("a[i]=%d\n",a[size]);
size++;
}
您的 malloc()
正在覆盖您之前的存储空间,space 只够存储一个整数!
a = (int *)malloc(sizeof(int));
^^^ assignment overwrites what you have stored!
相反,realloc()
数组:
a = realloc(a, sizeof(int)*(size+1));
通常的方法是首先分配一定数量的 space(大到足以覆盖大多数情况),然后根据需要使用 realloc
函数将其加倍。
一个例子:
#define INITIAL_ALLOCATED 32 // or enough to cover most cases
...
size_t allocated = INITIAL_ALLOCATED;
size_t size = 0;
...
int *a = malloc( sizeof *a * allocated );
if ( !a )
// panic
int val;
while ( fscanf( in, "%d", &val ) == 1 )
{
if ( size == allocated )
{
int *tmp = realloc( a, sizeof *a * allocated * 2 ); // double the size of the buffer
if ( tmp )
{
a = tmp;
allocated *= 2;
}
else
{
// realloc failed - you can treat this as a fatal error, or you
// can give the user a choice to continue with the data that's
// been read so far.
}
a[size++] = val;
}
}
我们首先将 32 个元素分配给 a
。然后我们从文件中读取一个值。如果我们不在数组的末尾(size
不等于 allocated
),我们将该值添加到数组的末尾。如果我们在数组的末尾,则使用 realloc
将其大小加倍。如果 realloc
调用成功,我们更新 allocated
变量以跟踪新大小并将值添加到数组。我们继续前进,直到到达输入文件的末尾。
每次达到限制时将数组的大小加倍可减少 realloc
调用的总数,如果您正在加载 lot,这可以节省性能值。
请注意,我将 realloc
的结果分配给了另一个变量 tmp
。 realloc
将 return NULL
如果它出于任何原因无法扩展数组。如果我们将 NULL
值分配给 a
,我们将失去对之前分配的内存的引用,从而导致内存泄漏。
另请注意,我们检查 fscanf
的结果而不是调用 feof
,因为 feof
不会 return true
直到我们'我们已经尝试读取文件末尾。
我有一个存储整数序列的文件。整数总数是未知的,所以如果我从文件中读取整数,我会继续使用 malloc() 来申请新内存。 我不知道我是否可以继续请求内存并将它们添加到数组的末尾。 Xcode 一直警告我 malloc() 行中的 'EXC_BAD_EXCESS'。 如果我一直从文件中读取整数,我该怎么做?
int main()
{
//1.read from file
int *a = NULL;
int size=0;
//char ch;
FILE *in;
//open file
if ( (in=fopen("/Users/NUO/Desktop/in.text","r")) == NULL){
printf("cannot open input file\n");
exit(0); //if file open fail, stop the program
}
while( ! feof(in) ){
a = (int *)malloc(sizeof(int));
fscanf(in,"%d", &a[size] );;
printf("a[i]=%d\n",a[size]);
size++;
}
fclose(in);
return 0;
}
- 不使用
malloc
,而是使用realloc
。 - 不要在
while
循环中使用feof(in)
。 See why.
int number;
while( fscanf(in, "%d", &number) == 1 ){
a = realloc(a, sizeof(int)*(size+1));
if ( a == NULL )
{
// Problem.
exit(0);
}
a[size] = number;
printf("a[i]=%d\n", a[size]);
size++;
}
像那样反复调用 malloc()
并不像您认为的那样。每次调用 malloc(sizeof(int))
时,它都会分配一个单独的新内存块,该内存块只够容纳一个整数。写入 a[size]
最终会为第一个值之后的每个值注销该数组的末尾。
这里你要的是realloc()
函数,例如
a = realloc(a, sizeof(int) * (size + 1));
if (a == NULL) { ... handle error ... }
修改您的代码,使 size
实际上是数组的 大小 ,而不是它的最后一个索引,这将有助于简化此代码,但这既不是这里也不是那里。
您还没有分配一个整数数组,您在这里分配了一个整数。因此,您需要分配默认数组大小,然后在即将超过 运行 时调整大小。这将在每次填满时将其大小调整 2。以这种方式调整大小可能不符合您的最佳利益,但您也可以为每个附加字段重新分配每个字段。
size_t size = 0;
size_t current_size = 2;
a = (int *)malloc(sizeof(int) * current_size);
if(!a)
handle_error();
while( ! feof(in) ){
if(size >= current_size) {
current_size *= 2;
a = (int *)realloc(a, sizeof(int) * current_size);
if(!a)
handle_error();
}
fscanf(in,"%d", &a[size] );;
printf("a[i]=%d\n",a[size]);
size++;
}
您的 malloc()
正在覆盖您之前的存储空间,space 只够存储一个整数!
a = (int *)malloc(sizeof(int));
^^^ assignment overwrites what you have stored!
相反,realloc()
数组:
a = realloc(a, sizeof(int)*(size+1));
通常的方法是首先分配一定数量的 space(大到足以覆盖大多数情况),然后根据需要使用 realloc
函数将其加倍。
一个例子:
#define INITIAL_ALLOCATED 32 // or enough to cover most cases
...
size_t allocated = INITIAL_ALLOCATED;
size_t size = 0;
...
int *a = malloc( sizeof *a * allocated );
if ( !a )
// panic
int val;
while ( fscanf( in, "%d", &val ) == 1 )
{
if ( size == allocated )
{
int *tmp = realloc( a, sizeof *a * allocated * 2 ); // double the size of the buffer
if ( tmp )
{
a = tmp;
allocated *= 2;
}
else
{
// realloc failed - you can treat this as a fatal error, or you
// can give the user a choice to continue with the data that's
// been read so far.
}
a[size++] = val;
}
}
我们首先将 32 个元素分配给 a
。然后我们从文件中读取一个值。如果我们不在数组的末尾(size
不等于 allocated
),我们将该值添加到数组的末尾。如果我们在数组的末尾,则使用 realloc
将其大小加倍。如果 realloc
调用成功,我们更新 allocated
变量以跟踪新大小并将值添加到数组。我们继续前进,直到到达输入文件的末尾。
每次达到限制时将数组的大小加倍可减少 realloc
调用的总数,如果您正在加载 lot,这可以节省性能值。
请注意,我将 realloc
的结果分配给了另一个变量 tmp
。 realloc
将 return NULL
如果它出于任何原因无法扩展数组。如果我们将 NULL
值分配给 a
,我们将失去对之前分配的内存的引用,从而导致内存泄漏。
另请注意,我们检查 fscanf
的结果而不是调用 feof
,因为 feof
不会 return true
直到我们'我们已经尝试读取文件末尾。