#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char *p;
p = (char *)malloc(4*sizeof(char));
strcpy(p, "abcdabcd");
printf("%s\n", p);
free(p);
printf("%s\n", p);
return 0;
}
我尝试在Ubuntu上运行上面的代码。这里我从malloc分配4个字节的内存。然后我尝试将8个字节复制到malloc分配的内存中。我没有得到任何警告或错误。我尝试释放内存块并尝试使用正在释放的相同内存,但同样没有任何问题。它打印出正确的字符串。有人可以解释一下这种行为吗?
答案 0 :(得分:3)
行为无法有意义地解释。您的程序显示 undefined 行为,这意味着任何事情都可能发生。 “任何事物”还包括您在实验中观察到的行为,即“打印正确的字符串”。
今天它“打印出正确的字符串”。明天它可能会崩溃。后天它可能会格式化您的硬盘。在未定义行为的概念下,这是完全允许的。
答案 1 :(得分:2)
明确正确的操作属于[未定义行为]类。
答案 2 :(得分:2)
启动程序时,可通过操作系统访问虚拟内存。通常虚拟页面具有一些最小尺寸(比如说4kb),这是它们处理的最小尺寸。
所以你在这个页面大小以下的malloc请求内存,并且可以使用整个块。 部分/无/所有此块可能被其他程序使用。但它在技术上仍然存在:
1 byte | 1 byte | 1 byte | 1 byte | more memory you don't have....
^ char p points here
然后开始转储从p 开始将字符串复制到内存中。所以你得到:
a | b | c | d | the rest of the chars start dumping into somebody elses space!
此重叠未定义。换句话说,我们可能有未使用的内存,因此一切正常今天。明天,该物理内存空间由操作系统保存,我们无法覆盖它。第二天,我们打破了其他一些计划。第二天,我们就错了。
正如其他人所说,C不会留意你。
答案 3 :(得分:1)
C语言不保证任何内存检查。基本上,如果你写入不属于你的内存(例如你写入超出数组界限的内存),或者你从内存中读取的不是你的内存(例如你从内存中读取,你已经放弃了它就放弃了它)不知道会发生什么。
但是,操作系统可能会也可能不会阻止您执行这些操作。通常,如果发生这种情况,您将收到“总线错误”或"Segmentation Fault"。但是,也不能保证这些事情都会发生。
最好的办法是采取防御性措施。跟踪阵列的持续时间,然后断言或以其他方式检查复制到阵列时是否超出阵列大小。
你可以做的另一件事是调试。 Valgrind是一个非常有效的工具,用于捕捉您描述的问题。它可以指示您读取或写入内存的情况,而不是malloc。它还可以识别泄漏,例如当你使用malloc内存然后忘记释放它时。
答案 4 :(得分:0)
我相信它会沿着块对齐分配,这就是为什么在这种情况下它会给你一些神奇的额外内存。尝试将其增加到更大的字节倍数(例如,16,64等等,它应该更精确,如果你超越它,它可能段错误)。虽然请记住,如果mallocg块之后的内存也是程序内存空间的一部分......那么你也不会得到段错误。
一般来说,只要你留在你的程序段内存中,你就可以愉快地读/写所有你想要的东西(当然是你自己的危险:D)。
如果你真的想检查你的程序,请在'valgrind'中运行它
答案 5 :(得分:0)
每个说你调用未定义行为的人都是正确的。
它似乎正常工作的原因可能是您的平台上堆管理器的特定实现的副作用。例如,许多内存管理器将分配四舍五入到一些方便的大小,最小的大小通常为8或16字节。您应从不依赖此类实施细节。
有些平台拥有在您开发程序时尝试捕获这些类型假设的工具。
答案 6 :(得分:0)
与其他人所说的一样,您的代码会导致 undefined 行为(任何事情都可能发生)。
您的堆内存分配器(malloc)不对存储的数据负责
您释放后的地区 。
了解malloc的职责将有助于您解释为什么会看到结果,为什么不正确的编程习惯以及为什么它不会一直工作。
malloc是glibc中的堆内存分配器(_int_malloc和_int_free)。您可以在此处查看其代码[http://code.woboq.org/userspace/glibc/malloc/malloc.c.html#_int_malloc]。
有人可以解释一下这种行为吗?
一个滑稽的例子有助于快速澄清您的问题。
考虑一下您从汽车旅馆( sbrk(2))租用一间房间(内存),该房间没有任何房间的钥匙(记忆< / STRONG>)! 。你去接待员( malloc )并要求一个房间(记忆),她给你一个可用的,你带走房间(<强>记忆)并使用它。
你完成了它,现在答应她你不会再次使用它(释放)。她在她的书中记录了你的房间(记忆)是免费的,可以分配给其他人。她希望完全把这个房间交给别人。
你有一段时间再来看看你的房间(接待员没有检查你),你很幸运,如果你发现没有人使用房间(它看起来像你离开时一样凌乱!)
接待员(malloc)的工作是尽快给你一个房间(记忆),相信你在离开(免费)后保守你的话。她的工作不是阻止你使用任何房间(记忆)!
如果您访问不允许的地方(只读区域),所有者(内核)会变得愤怒(例外)。
我是新手,我不确定它是否适合以这种方式回答。如果我错了,请告诉我 我强烈建议你通过malloc