根据需要扩展动态内存块

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);

您应该始终检查 malloccallocrealloc 的 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;
}