我想知道为什么这个程序不会出现段错误?
int main(void)
{
char *s = malloc(sizeof(char) * 5);
s = "Hello world !";
printf("%s\n", s);
}
我的意思是我只分配了5个大小的字符,但它会打印整个文本。
感谢。
答案 0 :(得分:5)
在
char* s = malloc(5);
是指向分配的内存
与
s = "Hello World !";
你将指向设置为内存中的另一个地方,你没有将字符串复制到s指向的位置。为此,您需要使用strcpy或memcpy。
答案 1 :(得分:4)
因为你没有做任何会导致的事情。
您有内存泄漏。就是这样。您正在分配字符串文字的地址。(作为数组的字符串文字衰减为指向它的第一个元素的指针)。并丢失旧分配的块地址。
如果您执行了strcpy(s,"hello world!");
,那么肯定会出现段错误。当然,你的程序会有不确定的行为。
另请注意,有一件事s = "hello world";
不会将字符串文字"hello world"
复制到s
。事实并非如此。只需拥有字符串文字的地址,然后将其传递给printf
和%s
格式说明符输出字符,直到它获得\0
并获得一个。 (因为字符串文字以null结尾)。
供您参考,
分段错误(aka segfault)是导致的常见情况 程序崩溃;它们通常与名为core的文件相关联。 Segfaults是由试图读取或写入非法的程序引起的 记忆位置。
在这里你没有做过这样的事情。
每当你分配动态分配的内存时,请记住一件事 - 在你完成工作后释放它。为此,请参阅此函数free()
。此外,最好检查malloc
的返回值。问题是当你通过s
指向字符串文字时,如果你试图修改它,你也可能会得到分段错误。因为字符串文字是不可修改的。
总之,代码在分配后不会使用分配的内存。那个记忆被泄露了。然后将指向字符串文字的指针分配给s
,然后打印出预期的内容。代码没有未定义的行为问题。
答案 2 :(得分:1)
在你编写的动态分配内存的任何代码中,你有2个职责关于任何分配的内存块:(1)总是保留一个指向起始地址的指针内存块,(2)当不再需要时,它可以释放。
你违反了规则(1),它阻止了能够满足规则(2)。
能够直观显示您正在做的事情的一种方法是使用调试器,或者只是在s
之后查看malloc
的地址,然后在分配{{1}后再查看"Hello world !"
的地址(注意:您还应该在进一步使用malloc
之前验证您对s
的调用是否成功)
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *s = malloc(sizeof(char) * 5);
if (!s) {
perror ("malloc - s");
return 1;
}
printf ("1. address of s : %p\n", s);
s = "Hello world !";
printf ("2. address of s : %p\n", s);
return 0;
}
示例使用/输出
$ ./bin/saddress
1. address of s : 0xa45010
2. address of s : 0x4006f5
地址有变化吗?为什么?保留malloc
ed s
的原始地址的变量是什么?你将如何free
你分配的记忆?
正如许多答案和评论中所解释的那样"Hello world !"
是在只读内存中创建的字符串文字,其地址是第一个的地址字符'H'
。当您致电s
时,您还请求malloc
新分配的内存块的地址并将其分配给s
。除非您在致电malloc
后保留free
中包含的原始地址,否则您无法s = "Hello world !";
您分配的内存 - 导致内存泄漏。基本上,当您分配s
时,您丢失了已分配的内存块的地址(因为"Hello world !"
现在将地址保存到#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *literal = "Hello world !";
char *s = malloc(sizeof(char) * 5);
if (!s) {
perror ("malloc - s");
return 1;
}
printf ("1. address of s : %p\n", s);
s = literal;
printf ("2. address of s : %p\n", s);
return 0;
}
的开头)
如果它仍然模糊,那么让我们看另一个完全相同的例子:
s
这里出现了完全相同的问题。您为"Hello world !"
分配,然后将literal
的地址(由指针s
保存)分配给free (s);
,失去对原始内存块的引用。
如果您尝试s
,问题会变得非常明显。
你如何解决这个问题? (不要覆盖s
开头)但是,既然你可以自由覆盖malloc
,你怎么保证你不会丢失你对{{1}分配的内存块的引用}}?它非常简单,只需用另一个指针保存地址,例如
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *literal = "Hello world !";
char *s = malloc(sizeof(char) * 5);
char *p = s;
if (!s) {
perror ("malloc - s");
return 1;
}
printf ("1. address of s : %p\n", s);
s = literal;
printf ("2. address of s : %p\n", s);
printf ("3. address of p : %p\n", p);
free (p);
return 0;
}
示例使用/输出
$ ./bin/saddress3
1. address of s : 0x1a96010
2. address of s : 0x400745
3. address of p : 0x1a96010
您可以查看valgrind
(或类似的内存错误检查程序),已释放所有内存并且没有内存错误。
如果您还有疑问,请询问。所有人都很乐意提供帮助。