正如一些人所说,这个块并没有像我想象的那样。我试图分配内存块,然后将字符串文本存储在其中,但现在再看一遍,很明显这不是我在这里所做的
如果你这样做有什么区别:
char* memory = malloc(sizeof("String"));
memory = "String"; //edit: memory leaked
printf("%s", memory);
free(memory); //edit
或者这个:
char* noMemory = "String";
printf("%s", noMemory);
在您的特定示例中,由于您首先分配memory
,然后为其分配"string"
地址,因此丢失了对原始分配的跟踪,因此您正在泄漏内存,并在尝试释放常量字符串"string"
时出现未定义的行为。
您需要使用strcpy(memory, "String");
来复制字符串。
除此之外,除非你只是这样做,否则你会浪费很多时钟周期,因为malloc
和free
不是空闲操作,它们需要时间,当然,复制字符串也需要一些操作。除此之外,分配有malloc
的内存将比实际字符串占用更多的空间,这既是因为malloc
和free
函数需要内存块"旁边"的一点信息才能完成它们的工作,也是因为通常情况下,大小会四舍五入到一些"好"的大小,例如8、16或32字节。这意味着调用malloc和free不仅浪费了时钟周期,而且使用的内存也比实际要求的要多。因此,您可能使用的不是7个字节,而是40或64个字节。
另一方面,如果你想修改字符串,那么你不能只使用"String"
的现有内存,因为这不能保证是"可写"内存,所以你最终会得到undefined behaviour
(这可能意味着任何现代操作系统都会崩溃)。然而,还有其他几种可能的解决方案,例如:
char local[15] = "String";
将为堆栈上的一个字符串提供相当于15个字节的空间-在空间量上没有开销[最多7个字节],我们可以忽略在堆栈上分配它的开销,因为如果你使用局部变量,它是一条必须存在的指令-它是所有局部变量的一条指令。
这个解决方案允许修改字符串(例如strcat(local, " abc");
使其成为"string abc"
。只需确保您知道自己在做什么,并且不要覆盖允许空间的末尾[并且不要忘记计算字符串末尾的零]。
这两个版本之间的区别如下。
- 在第一个版本中,您分配的内存正在泄漏,因为您没有使用返回的内存,而是立即用新值(指向静态分配的字符串的指针)覆盖它
- 此外,您可以将内存释放给静态分配的字符串,因为您已经丢失了分配的指针。这将导致未定义的行为
另一方面,第二个版本(几乎)可以。不过你应该得到一个警告,因为指针应该是"const"。
如果您想将字符串分配给分配的内存,您应该使用strcpy
,或者您可以使用strdup
,在这种情况下,您不需要malloc
,但您仍然必须释放它。另一种方法是为字符串静态分配一个数组,因为您已经知道该字符串了。
编辑
关于你在其他帖子中的评论:
如果您有一个文字字符串,它将存储在BSS段中。所以你可以直接使用它,而不需要为它分配额外的空间。然而,有一个限制,你不应该修改这样的字符串,因为这是未定义的行为。操作系统可能会选择将这些数据保存在受保护的内存中,这可能会导致程序发生故障,或者它可能会工作。