C 程序在 2 次重新分配后崩溃
C program crashes after 2 reallocs
我正在尝试编写一个小的 C 程序,但是一旦我尝试将 new_size 重新分配为 20,它就会崩溃。new_size 的每个值(在函数 reallocate_buffer 中) 20 岁以下完美。我不明白发生了什么。这是我的代码。
char* reallocate_buffer(char* buffer, unsigned new_size)
{
if (!buffer)
{
printf("Invallid buffer pointer given!\n");
printf("Press any key to continue...\n");
getchar();
exit(2);
}
realloc(buffer, sizeof(char) * new_size);
printf("Realloc is done...\n");
if (!buffer)
{
printf("Couldn't increase buffer size! Maybe out of memory?\n");
printf("Press any key to continue...\n");
getchar();
exit(1);
}
return buffer;
}
char* read_input(int* text_length)
{
unsigned bufsize = BUFFER_SIZE;
char* buffer = malloc(sizeof(char) * BUFFER_SIZE);
char c;
unsigned done = 0;
while((c = fgetc(stdin)) != EOF && c != '\n')
{
printf("C is now %d\n", c);
buffer[done] = c;
done += 1;
if (done == bufsize)
{
printf("Reallocating...\n");
printf("Buffer size was now: %d\n", bufsize);
bufsize += 5;
buffer = reallocate_buffer(buffer, bufsize);
printf("Buffer size is now: %d\n", bufsize);
}
}
/* Now increase size once more if necessary to place the [=10=] character */
if (bufsize == done)
{
printf("Reallocing once more...\n");
bufsize++;
reallocate_buffer(buffer, bufsize);
}
buffer[done] = '[=10=]';
return buffer;
}
int main(int argc, char * argv [])
{
printf("Please provide input:\n");
int line_size;
char* word = read_input(&line_size);
printf("You provided:\n%s\n", word);
printf("Press any key to continue...\n");
getchar();
free(word);
return 0;
}
您必须接收重新分配的缓冲区的地址作为 return 值,如
buffer = realloc(buffer, sizeof(char) * new_size);
让我们回顾一下:
在 C 中,为了让函数更改参数,它必须接收该参数作为指针。
但是如果该参数是一个指针会怎样呢?该函数必须将该指针作为指向指针的指针。
如您所见,realloc
获取的指针不是 void**
,而是 void*
,这意味着它无法更改该指针以指向内存。
从逻辑上讲,表达式
realloc(ptr,new_size);
毫无意义,内存地址已更改,但指针未更改。
这就是为什么realloc
returns新地址为void*
,而你必须更新原来的指针:
buffer = realloc(buffer, new_size);
P.S。
我不确定使用 visual studio 作为 C IDE 是最好的主意。
realloc()
的正确使用方法是
void *temp;
temp = realloc(buffer, new_size); // Note that: sizeof(char) == 1 ALWAYS
if (temp == NULL)
handle_allocation_error_or_exit(); // `buffer' is still valid here
else
buffer = temp;
您的方式它不存储返回的指针。您应该记住 realloc()
实际上可能 free()
指针并重新分配新内存。但前提是它能够成功地做到这一点。
不使用临时指针有与之相关的问题,有几点值得一提
- 您不能
free()
旧指针,因为您用 NULL
覆盖了它
- 出于同样的原因,现在您将无法访问以前在缓冲区指向的内存中的数据,您可能需要它来恢复,或将其写入永久存储或其他任何东西,但您会如果
realloc()
失败,将失去对它的引用。
当您使用 +8GB RAM 的系统时,确实很难让 malloc()
/calloc()
/realloc()
失败,但这并非不可能。就我而言,有时我是 运行 一个视频会议程序,共享一个 Windows 10 quemu 虚拟机,内存为 2GB,同时使用网络浏览器,有些 IDE 比如 Android Studio(占用大量内存)+ Android Emulator(又是 qemu)。您可能会对 RAM 的消耗速度感到惊讶,在这种情况下,程序可能会在 realloc()
时失败,您可能会丢失一些重要数据。
我正在尝试编写一个小的 C 程序,但是一旦我尝试将 new_size 重新分配为 20,它就会崩溃。new_size 的每个值(在函数 reallocate_buffer 中) 20 岁以下完美。我不明白发生了什么。这是我的代码。
char* reallocate_buffer(char* buffer, unsigned new_size)
{
if (!buffer)
{
printf("Invallid buffer pointer given!\n");
printf("Press any key to continue...\n");
getchar();
exit(2);
}
realloc(buffer, sizeof(char) * new_size);
printf("Realloc is done...\n");
if (!buffer)
{
printf("Couldn't increase buffer size! Maybe out of memory?\n");
printf("Press any key to continue...\n");
getchar();
exit(1);
}
return buffer;
}
char* read_input(int* text_length)
{
unsigned bufsize = BUFFER_SIZE;
char* buffer = malloc(sizeof(char) * BUFFER_SIZE);
char c;
unsigned done = 0;
while((c = fgetc(stdin)) != EOF && c != '\n')
{
printf("C is now %d\n", c);
buffer[done] = c;
done += 1;
if (done == bufsize)
{
printf("Reallocating...\n");
printf("Buffer size was now: %d\n", bufsize);
bufsize += 5;
buffer = reallocate_buffer(buffer, bufsize);
printf("Buffer size is now: %d\n", bufsize);
}
}
/* Now increase size once more if necessary to place the [=10=] character */
if (bufsize == done)
{
printf("Reallocing once more...\n");
bufsize++;
reallocate_buffer(buffer, bufsize);
}
buffer[done] = '[=10=]';
return buffer;
}
int main(int argc, char * argv [])
{
printf("Please provide input:\n");
int line_size;
char* word = read_input(&line_size);
printf("You provided:\n%s\n", word);
printf("Press any key to continue...\n");
getchar();
free(word);
return 0;
}
您必须接收重新分配的缓冲区的地址作为 return 值,如
buffer = realloc(buffer, sizeof(char) * new_size);
让我们回顾一下:
在 C 中,为了让函数更改参数,它必须接收该参数作为指针。
但是如果该参数是一个指针会怎样呢?该函数必须将该指针作为指向指针的指针。
如您所见,realloc
获取的指针不是 void**
,而是 void*
,这意味着它无法更改该指针以指向内存。
从逻辑上讲,表达式
realloc(ptr,new_size);
毫无意义,内存地址已更改,但指针未更改。
这就是为什么realloc
returns新地址为void*
,而你必须更新原来的指针:
buffer = realloc(buffer, new_size);
P.S。 我不确定使用 visual studio 作为 C IDE 是最好的主意。
realloc()
的正确使用方法是
void *temp;
temp = realloc(buffer, new_size); // Note that: sizeof(char) == 1 ALWAYS
if (temp == NULL)
handle_allocation_error_or_exit(); // `buffer' is still valid here
else
buffer = temp;
您的方式它不存储返回的指针。您应该记住 realloc()
实际上可能 free()
指针并重新分配新内存。但前提是它能够成功地做到这一点。
不使用临时指针有与之相关的问题,有几点值得一提
- 您不能
free()
旧指针,因为您用NULL
覆盖了它
- 出于同样的原因,现在您将无法访问以前在缓冲区指向的内存中的数据,您可能需要它来恢复,或将其写入永久存储或其他任何东西,但您会如果
realloc()
失败,将失去对它的引用。
当您使用 +8GB RAM 的系统时,确实很难让 malloc()
/calloc()
/realloc()
失败,但这并非不可能。就我而言,有时我是 运行 一个视频会议程序,共享一个 Windows 10 quemu 虚拟机,内存为 2GB,同时使用网络浏览器,有些 IDE 比如 Android Studio(占用大量内存)+ Android Emulator(又是 qemu)。您可能会对 RAM 的消耗速度感到惊讶,在这种情况下,程序可能会在 realloc()
时失败,您可能会丢失一些重要数据。