@JosephSible 已经给你一个很好的答案,但还有一点需要说明realloc 的使用。我在原始问题下的评论中提到了这一点。使用realloc 时,您必须始终使用realloc 使用临时 指针来捕获realloc 的返回。
为什么?当(不是如果)realloc 失败时,它返回NULL。如果您将返回值直接分配给您尝试重新分配的指针,您将覆盖指向现有内存块的指针,NULL 失去对原始块的引用,从而造成内存泄漏。例如,您不想:
*buffer = realloc (*buffer, 2); /* sizeof(char) is always 1 */
相反,在将重新分配的块分配给原始指针之前,请使用临时指针并验证重新分配是否成功,例如
void * tmp = realloc (*buffer, 2);
if (!tmp) { /* validate EVERY allocation & reallocation */
perror ("realloc-*buffer");
exit (EXIT_FAILURE); /* or handle as desired, e.g return NULL, etc.. */
}
*buffer = tmp; /* now assign the reallocated block to your pointer */
您原来的帖子上有几个 cmets。回想一下 C 中的字符串必须以 nul-terminating 字符结尾。您不能简单地分配buffer[0] = 'H'; 并将buffer 视为字符串。 nul-termianting 字符('\0',或简称为0)必须跟在后面,所以在调用printf("%s\n", *buffer);之前需要buffer[1] = 0;
避免在代码中使用 幻数。您的 change_buffer_size() 函数使用幻数 2 将重新分配硬编码为大小。 (不是很有用)。相反,至少将所需的大小作为参数传递,以便您的函数可重用,例如
char *change_buffer_size (char **buffer, size_t nchar)
{
void *tmp = realloc (*buffer, nchar * sizeof **buffer);
if (!tmp) { /* validate EVERY allocation/reallocation */
perror ("change_buffer_size()-realloc");
return NULL;
}
return *buffer = tmp; /* assign new block to *buffer, return */
}
(注意:将返回类型更改为char* 允许您通过返回指示函数的成功/失败以及成功时直接访问重新分配的内存块)
现在您想将缓冲区重新分配给 2 个字符,只需将 2 传递为 nchar 等。结合一个简短的示例,一次重新分配并添加一个字符到您的缓冲区(同时确保它总是 nul-terminated) 可能类似于以下内容:
#include <stdio.h>
#include <stdlib.h>
char *change_buffer_size (char **buffer, size_t nchar)
{
void *tmp = realloc (*buffer, nchar * sizeof **buffer);
if (!tmp) { /* validate EVERY allocation/reallocation */
perror ("change_buffer_size()-realloc");
return NULL;
}
return *buffer = tmp; /* assign new block to *buffer, return */
}
int main (void) {
size_t nchar = 1; /* character counter */
char *str = "hello world!", *buffer = NULL;
for (int i = 0; str[i]; i++) {
if (!change_buffer_size(&buffer, nchar + 1)) /* alloc nchar + 1 */
return 1;
buffer[nchar-1] = str[i]; /* copy char from str to buffer */
buffer[nchar++] = 0; /* nul-terminate buffer */
printf ("buffer: '%s'\n", buffer); /* print current buffer contents */
}
free (buffer); /* don't forget to free what you allocate */
}
(注意:不要忘记free()你分配的内存。是的,在这里它会在程序退出时被释放,但要尽早养成好习惯——你不会一直在工作在main())
使用/输出示例
$ ./bin/realloccharbuf
buffer: 'h'
buffer: 'he'
buffer: 'hel'
buffer: 'hell'
buffer: 'hello'
buffer: 'hello '
buffer: 'hello w'
buffer: 'hello wo'
buffer: 'hello wor'
buffer: 'hello worl'
buffer: 'hello world'
buffer: 'hello world!'
内存使用/错误检查
在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您都有 2 个职责:(1)始终保留指向起始地址的指针内存块,因此,(2) 当不再需要它时可以释放。
您必须使用内存错误检查程序来确保您不会尝试访问内存或写入超出/超出分配块的边界,尝试读取或基于未初始化的值进行条件跳转,最后,以确认您释放了已分配的所有内存。
对于 Linux,valgrind 是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。
$ valgrind ./bin/realloccharbuf
==19740== Memcheck, a memory error detector
==19740== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==19740== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==19740== Command: ./bin/realloccharbuf
==19740==
buffer: 'h'
buffer: 'he'
buffer: 'hel'
buffer: 'hell'
buffer: 'hello'
buffer: 'hello '
buffer: 'hello w'
buffer: 'hello wo'
buffer: 'hello wor'
buffer: 'hello worl'
buffer: 'hello world'
buffer: 'hello world!'
==19740==
==19740== HEAP SUMMARY:
==19740== in use at exit: 0 bytes in 0 blocks
==19740== total heap usage: 13 allocs, 13 frees, 1,114 bytes allocated
==19740==
==19740== All heap blocks were freed -- no leaks are possible
==19740==
==19740== For counts of detected and suppressed errors, rerun with: -v
==19740== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认您已释放已分配的所有内存并且没有内存错误。
检查一下,如果您有任何问题,请告诉我。