根据需要扩展动态内存块
Expanding a dynamic memory block as needed
我想将数据分配给一块内存,但我不知道我需要的大小是多少。
例如,下面只是一个简单的例子来说明目的:
char *str = (char*)malloc(2);
for (int i = 1; i < 10; i++) {
str[i] = i;
realloc(str, strlen(str) + 1);
}
printf("%s\n", str);
前面的代码打印未知符号,如下所示:
那是什么问题呢?
你正在分配内存,没关系。你在里面写一个字符
限制,那也可以。但是你用strlen
,那不行,因为
strlen
需要一个有效的字符串,您没有传递字符串。
在 C 中,字符串只是以字符结尾的字符序列
'[=13=]'
-终止字节。你没有这样做,所以 strlen
将超出
限制直到它找到 '[=13=]'
终止字节并且这是未定义的
行为。
另外realloc
可能扩展内存时改变内存位置。你
没有考虑到这一点。如果 realloc
return 是一个不同的指针,旧的
位置无效,下一个 realloc
调用将产生未定义的行为。
您填充数据的方式,您甚至不需要 strlen
调用,i
已经为您提供了该信息。
修复您的代码:
char *str = calloc(2, 1);
if(str == NULL)
{
// error handling
// do not continue
return;
}
for (int i = 0; i < 9; i++) {
str[i] = i + 1 + '0';
str[i+1] = 0; // making sure you have a valid c-string
char *tmp = realloc(str, strlen(str) + 2);
if(tmp == NULL)
{
// error handling,
// do not continue
free(str);
return;
}
// making sure that str points to the new location
// if realloc returned a different pointer
str = tmp;
}
printf("%s\n", str);
free(str);
您应该始终检查 malloc
、calloc
、realloc
的 return 值。
realloc
也应该是 strlen(str) + 2
。 +2
因为你要加
一个新字符,你必须有 space 作为 '[=13=]'
终止字节。
请注意,对于第一次分配,我使用了 calloc
,因为 calloc
也设置了
分配的内存为0,非常适合初始化。但不管怎样,你
每次添加新字符时都应设置 '[=13=]'
终止字节
(str[i+1] = 0;
行)。我还存储了值 i + '0'
,这很可能是
你想要什么。 1 != '1'
,因为字符 '1'
的值为 49,而不是 1。
参见:ASCII table.
我已将 str[i] = i + '0';
更改为 str[i] = i + 1 + '0';
,因为它
似乎您希望字符串以 '1'
开头,而不是 '0'
.
永远不要忘记释放您分配的内存。你可以释放内存
在程序结束时或更好,当您不再需要它时。
那是什么问题呢?
很简单,i
中的值是
0x00000000
0x00000001
...
0x00000009
(不适合一个字符)
并且这些值不属于 'printable' ascii 字符集。
建议在分配给数组的每个值中添加 0
(0x30)。
此外,建议在每次作业时将 int
i
转换为 (char)
数组中的值不会构成 'string',因为没有终止 NUL (0x00) 字节。
以下为狮子王的评论编辑
建议写类似下面的代码:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
char *str = malloc(2); // do not 'cast' the returned value
if( !str )
{
perror( "malloc failed" ); // output enclosed text and reason
// system thinks the 'malloc` failed
// to `stderr`
exit( EXIT_FAILURE );
}
// implied else, malloc successful
int i;
for ( i = 0; i < MAX_CHARS; i++)
{
str[i] = (char)('0' + i);
char *temp = realloc(str, i+3); // assign to temp variable
// and check if successful
// to avoid causing a memory
// leak when it fails
if( !temp )
{
perror( "realloc failed" );
free( str ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, realloc successful
str = temp; // update the target variable
}
// terminate the string
str[ i ] = '[=10=]';
printf("%s\n", str);
free( str ); // cleanup
return 0;
}
我想将数据分配给一块内存,但我不知道我需要的大小是多少。
例如,下面只是一个简单的例子来说明目的:
char *str = (char*)malloc(2);
for (int i = 1; i < 10; i++) {
str[i] = i;
realloc(str, strlen(str) + 1);
}
printf("%s\n", str);
前面的代码打印未知符号,如下所示:
那是什么问题呢?
你正在分配内存,没关系。你在里面写一个字符
限制,那也可以。但是你用strlen
,那不行,因为
strlen
需要一个有效的字符串,您没有传递字符串。
在 C 中,字符串只是以字符结尾的字符序列
'[=13=]'
-终止字节。你没有这样做,所以 strlen
将超出
限制直到它找到 '[=13=]'
终止字节并且这是未定义的
行为。
另外realloc
可能扩展内存时改变内存位置。你
没有考虑到这一点。如果 realloc
return 是一个不同的指针,旧的
位置无效,下一个 realloc
调用将产生未定义的行为。
您填充数据的方式,您甚至不需要 strlen
调用,i
已经为您提供了该信息。
修复您的代码:
char *str = calloc(2, 1);
if(str == NULL)
{
// error handling
// do not continue
return;
}
for (int i = 0; i < 9; i++) {
str[i] = i + 1 + '0';
str[i+1] = 0; // making sure you have a valid c-string
char *tmp = realloc(str, strlen(str) + 2);
if(tmp == NULL)
{
// error handling,
// do not continue
free(str);
return;
}
// making sure that str points to the new location
// if realloc returned a different pointer
str = tmp;
}
printf("%s\n", str);
free(str);
您应该始终检查 malloc
、calloc
、realloc
的 return 值。
realloc
也应该是 strlen(str) + 2
。 +2
因为你要加
一个新字符,你必须有 space 作为 '[=13=]'
终止字节。
请注意,对于第一次分配,我使用了 calloc
,因为 calloc
也设置了
分配的内存为0,非常适合初始化。但不管怎样,你
每次添加新字符时都应设置 '[=13=]'
终止字节
(str[i+1] = 0;
行)。我还存储了值 i + '0'
,这很可能是
你想要什么。 1 != '1'
,因为字符 '1'
的值为 49,而不是 1。
参见:ASCII table.
我已将 str[i] = i + '0';
更改为 str[i] = i + 1 + '0';
,因为它
似乎您希望字符串以 '1'
开头,而不是 '0'
.
永远不要忘记释放您分配的内存。你可以释放内存 在程序结束时或更好,当您不再需要它时。
那是什么问题呢?
很简单,i
中的值是
0x00000000
0x00000001
...
0x00000009
(不适合一个字符)
并且这些值不属于 'printable' ascii 字符集。
建议在分配给数组的每个值中添加 0
(0x30)。
此外,建议在每次作业时将 int
i
转换为 (char)
数组中的值不会构成 'string',因为没有终止 NUL (0x00) 字节。
以下为狮子王的评论编辑
建议写类似下面的代码:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
char *str = malloc(2); // do not 'cast' the returned value
if( !str )
{
perror( "malloc failed" ); // output enclosed text and reason
// system thinks the 'malloc` failed
// to `stderr`
exit( EXIT_FAILURE );
}
// implied else, malloc successful
int i;
for ( i = 0; i < MAX_CHARS; i++)
{
str[i] = (char)('0' + i);
char *temp = realloc(str, i+3); // assign to temp variable
// and check if successful
// to avoid causing a memory
// leak when it fails
if( !temp )
{
perror( "realloc failed" );
free( str ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, realloc successful
str = temp; // update the target variable
}
// terminate the string
str[ i ] = '[=10=]';
printf("%s\n", str);
free( str ); // cleanup
return 0;
}