你怎么知道用malloc()分配多少空间?

时间:2009-08-08 04:22:51

标签: c memory-management malloc char sizeof

我是C新手,我来自C#。我一直在学习内存管理和malloc()功能。我也遇到过这段代码:

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

我不明白这是为a_persons_name分配多少空间。是分配2个字符(例如AB)还是别的?

我也知道你有时可以使用malloc获得“幸运”并使用未分配的空间(这会导致数据损坏和seg错误)。那么我怎么知道我分配了多少空间以及我需要多少空间呢?

6 个答案:

答案 0 :(得分:17)

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

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

  • 为任何给定字符串定义最大大小,分配该大小+ 1(对于空终止符),最多读取多个字符,如果提供的字符太多则错误或盲目截断。非常用户友好。

  • 分阶段重新分配(最好使用几何系列,例如加倍,以避免二次行为),并继续阅读直到达到结束。编码并不容易。

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

答案 1 :(得分:5)

嗯,首先,sizeof(char)始终是1,所以你可以malloc(3)

您要分配的内容有足够的空间容纳三个角色。但请记住,您需要一个用于C字符串的空终止符。

你倾向于找到的东西是:

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

为名称和终结符字符获取足够的存储空间(请记住,字符串“xyzzy”存储在内存中:

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

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

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

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

答案 2 :(得分:3)

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

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

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

这将为49个字符的字符串分配足够的空间(C样式的字符串必须以NULL('\0')字符终止),不包括NULL字符,并在该内存中指向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个字符分配足够的空间,并且为NULL字符 第二行尝试将20个字符(19 + NULL)复制到该内存空间。这会超出缓冲区并可能导致令人难以置信的诙谐,例如覆盖相邻内存或导致段错误。

第三行可能有效,例如,如果在someString旁边有分配的内存,那么“Hello there,world!”遇到了那个内存空间,它可能会打印你的字符串以及下一个内存空间中的内容。如果第二个空格被NULL终止,那么它将停止 - 除非它不是,在这种情况下它会徘徊并最终发生段错误。

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

答案 3 :(得分:1)

您对malloc的呼叫将分配3个字节的内存。 sizeof(char)是1个字节,显式指示2个字节。这为大小为2的字符串(以及终止字符)提供了足够的空间

答案 4 :(得分:1)

这将分配三个字节; 1表示sizeof(char),加上2。只是看到这条线脱离了上下文,我无法知道为什么会以这种方式分配它或者它是否正确(对我来说看起来很可疑)。

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

答案 5 :(得分:1)

第一点 - 永远不要将绝对数字放在malloc的参数中,总是使用sizeof和倍数是一个好习惯。如上所述,为某些类型分配的存储器随编译器和平台而变化。为了保证为'blob'类型的数组获得足够的空间,最好使用这样的东西:

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

这样,无论什么类型,但它在内存中看起来都会得到恰当的数量。

其次,段错误等 C,作为低级语言,没有边界检查。这意味着没有什么可以检查你正在查看实际上不在数组中的索引。实际上它并不会阻止你在任何地方访问内存,即使它不属于你的程序(虽然你的操作系统可能,这就是段错误)。这就是为什么每当你在C中传递一个数组时你也需要传递它的长度,这样接收数组的函数就知道它有多大。不要忘记'数组'实际上只是指向第一个元素的指针。 传递字符串时这非常无用 - 每个字符串参数都会成为两个参数,因此使用了作弊。任何标准C字符串都以NULL结尾。字符串中的最后一个字符应为ASCII值0.任何字符串函数都会沿着数组工作,直到它们看到然后停止。这样他们就不会超出阵列,但如果由于某种原因它不存在,他们就会。 这被理解

strlen("Hello")

是5,但要存储它,你还需要一个字符。 E.g:

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

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