代码之家  ›  专栏  ›  技术社区  ›  Kredns

如何知道使用malloc()分配多少空间?

  •  10
  • Kredns  · 技术社区  · 17 年前

    我是个彻头彻尾的C族新手,我来自C。我一直在学习内存管理和 malloc()

    char *a_persons_name = malloc(sizeof(char) + 2);
    

    我不明白的是,这要分配多少空间 a_persons_name . 它是分配2个字符(例如AB)还是其他什么?

    我也知道,你有时也能得到“幸运” malloc 并使用未分配的空间(这可能导致数据损坏和seg故障)。那么,我如何知道分配了多少空间以及需要多少空间呢?

    6 回复  |  直到 17 年前
        1
  •  18
  •   Barry Kelly    17 年前

    该代码段为2个字符的名称分配了足够的空间。

    通常,字符串缓冲区将从某处填充,即i/O。如果字符串的大小事先未知(例如,从文件或键盘读取),则通常使用以下三种方法之一:

    • 分阶段重新分配(最好使用几何级数,例如加倍,以避免二次行为),并继续读取,直到达到终点。编写代码不是很容易。

    • 分配一个固定的大小,并希望它不会被超过,当这个假设失败时,它会崩溃(或被拥有)。容易编码,容易破解。例如,请参见 gets 在标准C库中。( )

        2
  •  5
  •   paxdiablo    16 年前

    首先, sizeof(char) 总是1,所以你可以 malloc(3) .

    您往往会发现以下情况:

    #define NAME_SZ 30
    : : :
    char *name = malloc (NAME_SZ+1);
    

    +---+---+---+---+---+----+
    | x | y | z | z | y | \0 |
    +---+---+---+---+---+----+
    

    有时对于非基于字符的数组,您会看到:

    int *intArray = malloc (sizeof (int) * 22);
    

    这将为22个整数分配足够的空间。

        3
  •  3
  •   Carson Myers    17 年前

    malloc() 将分配一个内存块,如果成功,则返回指向该内存的指针,如果失败,则返回NULL。内存块的大小由指定 malloc 的参数,以字节为单位。

    这个 sizeof 运算符以字节为单位给出其参数的大小。

    char *someString = malloc(sizeof(char) * 50)
    

    这将为49个字符的字符串分配足够的空间(C样式的字符串必须以NULL结尾)( '\0' someString 在那记忆里。

    看起来你问题中的代码应该是 malloc(sizeof(char) * 2); sizeof(char) + 2

    注意 sizeof(char) 保证始终等于1(字节)--但其他类型(如long)的内存表示形式可能因编译器而异。

    对于动态分配的内存,如果您尝试在已分配的内存之外进行读/写,那么您就(不)幸运了。

    例如

    char *someString = malloc(10);
    strcpy(someString, "Hello there, world!");
    printf("%s\n", someString);
    

    第一行为9个字符和一个空字符分配了足够的空间。
    第二行尝试将20个字符(19+NULL)复制到该内存空间。这会导致缓冲区溢出,并可能导致某些异常情况,如覆盖相邻内存或导致segfault。

    第三行可能会工作,例如,如果在某个字符串旁边有分配的内存,并且“Hello there,world!”运行到该内存空间,它可能会打印您的字符串以及下一个内存空间中的任何内容。如果第二个空间以NULL结尾,那么它将停止——除非它不是,否则在这种情况下,它将漂移并最终发生故障。

    这个例子是一个非常简单的操作,但很容易出错。C是个棘手的问题——小心点。

        4
  •  1
  •   Brandon E Taylor    17 年前

    你的电话 malloc 将分配3个字节的内存。 sizeof(char) 显式指示为1字节和2字节。这为大小为2的字符串(以及终止字符)提供了足够的空间

        5
  •  1
  •   Fred Larson    17 年前

    您需要分配足够的内存来保存需要放入的内容。例如,如果要分配内存来保存字符串,则需要分配足够的内存来保存预期的最长字符串加上终止null的一个字节。如果要处理ASCII字符串,这很简单:每个字符一个字节加一个字节。如果使用unicode字符串,事情会变得更复杂。

        6
  •  1
  •   WillW    17 年前

    第一点-最好不要在malloc的参数中使用绝对数,始终使用sizeof和倍数。如上所述,为某些类型分配的内存因编译器和平台而异。为了保证为“blob”类型的数组获取足够的空间,最好使用如下内容:

    blob *p_data = malloc(sizeof(blob) * length_of_array);
    

    这样,无论类型是什么,不管它在内存中看起来如何,您都会得到正确的数量。

    C、 作为一种低级语言,它没有边界检查。这意味着如果您正在查看的索引实际上不在数组中,则无需进行任何检查。事实上,它不会阻止你访问任何地方的内存,即使它不属于你的程序(尽管你的操作系统可能会,这就是segfault)。这就是为什么,无论何时在C中传递数组,都需要传递它的长度,以便接收数组的函数知道它有多大。不要忘记,“数组”实际上只是指向第一个元素的指针。 当传递字符串时,这是非常没有帮助的——每个字符串参数都会变成两个参数,因此使用了欺骗。任何标准C字符串都以NULL结尾。字符串中的最后一个字符应为ASCII值0。任何字符串函数都会沿着数组工作,直到它们看到并停止为止。这样它们就不会溢出阵列,但如果由于某种原因阵列不存在,它们就会溢出。 这是被理解的

    strlen("Hello")
    

    是5,但要存储它,还需要一个字符。例如。:

    const char str1 = "Hello";
    char *str2 = malloc(sizeof(char) * (strlen(str1) + 1));
    strcpy(str2, str1);
    

    是的,sizeof(char)是不必要的,因为它被定义为1,但我发现它更清晰,这绝对是一个好习惯。