根据需要扩展动态内存块

时间:2018-02-05 01:50:58

标签: c dynamic-memory-allocation

我想将数据分配给一块内存,但我不知道我需要的尺寸是多少。
例如,以下只是一个简单的例子,说明了目的:

char *str = (char*)malloc(2);
for (int i = 1; i < 10; i++) {
    str[i] = i;
    realloc(str, strlen(str) + 1);
}
printf("%s\n", str);

以前的代码会打印如下所示的未知符号:

那么问题是什么呢?

2 个答案:

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

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