我想将数据分配给一块内存,但我不知道我需要的尺寸是多少。
例如,以下只是一个简单的例子,说明了目的:
char *str = (char*)malloc(2);
for (int i = 1; i < 10; i++) {
str[i] = i;
realloc(str, strlen(str) + 1);
}
printf("%s\n", str);
以前的代码会打印如下所示的未知符号:
那么问题是什么呢?
答案 0 :(得分:1)
你正在分配内存,没关系。你正在写一个角色
限制,也没关系。但是你使用strlen
,那不行,因为
strlen
需要一个有效的字符串,你没有传递字符串。
在C中,字符串只是以字符串结尾的字符序列
'\0'
- 终止字节。你没有这样做,所以strlen
将超越
限制,直到找到'\0'
- 终止字节,这是未定义的
行为。
在展开内存时,realloc
也可能更改内存位置。您
没有考虑到这一点。如果realloc
返回不同的指针,则为旧指针
位置无效,下一个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
的返回值。
realloc
也应为strlen(str) + 2
。 +2
,因为您要添加
一个新字符,你必须有'\0'
的空间 - 终止字节。
请注意,对于我使用calloc
的第一次分配,因为calloc
也设置了
分配的内存为0,非常适合初始化。但无论如何,你
应该在添加新字符时设置'\0'
- 终止字节每时间
(str[i+1] = 0;
行)。我还存储了最有可能的值i + '0'
你想要什么。 1 != '1'
,因为字符'1'
的值为49,而不是1。
请参阅:ASCII table。
我已将str[i] = i + '0';
更改为str[i] = i + 1 + '0';
,因为它
似乎您希望字符串以'1'
开头,而不是'0'
。
也永远不要忘记释放你已经分配的记忆。你可以释放记忆 在课程结束时或者更好的是,当你不再需要它时。
答案 1 :(得分:0)
那是什么问题呢?
非常简单,i
中的值是
00000000
00000001
...
0x00000009
(不适合char)
并且这些值不属于“可打印”的一部分。 ascii字符集。
建议在将每个值分配给数组时添加0
(0x30)。
另外,建议在每个作业中将int
i
转换为(char)
数组中的值不会产生&#39;字符串&#39;因为没有终止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 ] = '\0';
printf("%s\n", str);
free( str ); // cleanup
return 0;
}