Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中创建动态分配的字符串?_C_String_Dynamic Allocation - Fatal编程技术网

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

如何在C中创建动态分配的字符串?,c,string,dynamic-allocation,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++] = '

我不明白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;
}
#包括
#包括
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);
返回0;
}

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


malloc
通常返回给定大小的内存块,供您使用。在您的情况下,恰好在您正在触摸的块之外有有效内存。记忆是不应该被触摸的
malloc
可能会将该内存用于内部管理,它可能会将该内存作为一些
malloc
调用的结果,或者完全其他的结果。不管它是什么,它都不是你的,触摸它会产生未定义的行为。

当前C标准第7.20.3节部分规定:

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

这将由实现定义。它可以发送空指针,或者如上所述,通过执行
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).
做两件事总是好的:

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

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

    。。。在调用
    malloc

    后,您将覆盖未分配的内存。这看起来可能有用。但是当调用
    free
    时,如果堆函数试图返回内存块,则会遇到麻烦

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

    因此您有一个未定义的行为。

    您的malloc(0)是错误的。正如其他人指出的那样,可能最终会分配一点内存,也可能不会,但不管malloc对0实际做了什么,在这个简单的示例中,您都应该分配至少3*sizeof(char)字节的内存

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

    除了在幕后,这些语言必须做同样的事情,分配更多内存和复制现有数据。如果一个人关心高性能C,那么在哪里花费时间的时间就更清楚了,而C++、爪哇、C等的隐藏隐藏了昂贵的操作,方便了使用类。这些类可能非常聪明(例如分配的内存比以防万一所需的内存要多),但是如果您想从硬件中获得最佳性能,那么您就必须随时准备


    这类问题是Facebook和Twitter等运营商在发展其服务时遇到的困难背后的原因。这些方便但低效的类方法迟早会导致一些不可持续的结果。

    谢谢!有没有办法检查我是否为我的字符串分配了正确的内存量?@dyxh:我不完全确定你在问什么,但如果你问是否有任何工具可以调试类似的问题,那么是的:在我的脑海里,有Valgrind和AddressSanitizer。如果您询问如何正确分配内存,则需要传递字符串的大小,包括尾随的NUL字节。如果您询问是否可以在代码中检查内存块是否足够大,则没有标准方法;一些实现可能提供这种功能,而另一些可能不提供;这种功能不是必需的。