如何在C中创建动态分配的字符串?

时间:2013-08-14 05:20:41

标签: c string dynamic-allocation

我不明白C中动态分配的字符串是如何工作的。下面,我有一个例子,我认为我已经创建了一个指向字符串的指针,并将其分配给0内存,但我仍然可以给它字符。我显然做错了什么,但是什么?

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
char *str = malloc(0);
int i;
str[i++] = 'a';
str[i++] = 'b';
str[i++] = '\0';
    printf("%s\n", str);

    return 0;
}

5 个答案:

答案 0 :(得分:3)

您正在做的是未定义的行为。它似乎现在可以工作,但不需要工作,如果有任何变化可能会中断。

malloc通常会返回您可以使用的给定大小的内存块。在你的情况下,恰好碰到你正在触摸的那个块之外的有效内存。那个记忆不应该被触动; malloc可能会使用该内存进行内部管理,它可能会将这些内存作为某些malloc调用的结果,或完全不同的内容。无论是什么,它都不是你的,触摸它会产生不确定的行为。

答案 1 :(得分:0)

当前C标准的第7.20.3节部分说明:

“如果请求的空间大小为零,则行为为 实现定义:返回空指针,或者 行为就像大小是一些非零值,除了 返回的指针不得用于访问对象。“

这将是实现定义。它可以发送一个NULL指针,或者提到一些无法引用的东西

答案 2 :(得分:0)

通过执行malloc(0),您将创建一个NULL指针或一个可以传递给free的唯一指针。那条线没什么问题。问题在于执行指针运算并将值分配给尚未分配的内存时。因此:

str[i++] = 'a'; // Invalid (undefined).
str[i++] = 'b'; // Invalid (undefined).
str[i++] = '\0'; // Invalid (undefined).

printf("%s\n", str); // Valid, (undefined).

做两件事总是好的:

  1. 不要malloc 0字节。
  2. 检查以确保malloc ed的内存块有效。
  3. ...要检查malloc请求的内存块是否有效,请执行以下操作:

    if ( str == NULL ) exit( EXIT_FAILURE );
    

    ...致电malloc后。

答案 3 :(得分:0)

您正在覆盖未分配的内存。这可能看似有效。但是当你调用free时,你会遇到麻烦,其中堆函数试图给回内存块。

每个malloc()返回的内存块都有一个标题和一个预告片。这些结构至少保持分配的内存的大小。有时你会有额外的警卫。您正在覆盖此堆内部结构。这就是free()抱怨或崩溃的原因。

所以你有一个未定义的行为。

答案 4 :(得分:0)

你的malloc(0)错了。正如其他人已经指出的那样,可能会或者可能不会最终分配一些内存,但不管malloc实际上用0做什么,你应该在这个简单的例子中分配至少3 * sizeof(char)字节的内存。

所以我们这里有一个正确的麻烦。假设您为字符串分配了20个字节,然后用19个字符和一个空填充它,从而填充内存。到现在为止还挺好。但是,请考虑您希望在字符串中添加更多字符的情况;因为你只分配了20个字节并且你已经使用过它们,所以你不能将它们放在适当位置。您所能做的就是分配一个全新的缓冲区(比如40个字节),将原始的19个字符复制到其中,然后在末尾添加新字符,然后释放原始的20个字节。声音低效不是吗。这是低效的,分配内存需要做很多工作,而且与其他语言(例如C ++)相比,它听起来像是一个特别大量的工作,你只需要将字符串连接到str1 + str2。

除了在引擎盖下,这些语言必须完全相同的事情分配更多的内存和复制现有的数据。如果一个人关心高性能C会让你更清楚地花时间,而C ++,Java,C#等隐藏了方便使用的类背后的昂贵操作。这些类可以非常聪明(例如,为了以防万一,分配更多的内存而不是严格必要的内容),但如果你有兴趣从你的硬件中提取最佳性能,那么你必须要掌握这些内容。

这类问题正是Facebook和Twitter等运营部门在发展服务方面遇到的困难所在。迟早那些方便但效率低下的课程方法会增加不可持续的东西。