#include<stio.h> main() { int *p,i; p = (int*)malloc(sizeof(int)); printf("Enter:"); scanf("%d",p); for(i=1;i<3;i++) { printf("Enter"); scanf("%d",p+i); } for(i=0;i<3;i++) { printf("No:%d\n",*(p+i)); } getch(); return 0; }
在这个C程序中,内存是在没有分配的情况下访问的。程序可以工作。如果没有分配就访问内存会出现什么问题?如果是,那么存储大小未提前知道的整数数据集合的解决方案是什么?
答案 0 :(得分:8)
是的,它会导致未定义的行为。问题是工作这里纯粹是因为运气而且可能随时崩溃。解决方案是使用malloc
分配内存。例如,如果要为count
个元素分配内存,则可以使用int* p = (int*)malloc(sizeof(int)*count);
。从这里开始,您可以访问p
作为count
元素的数组。
答案 1 :(得分:3)
它可能有效,因为*p
之后的内存都可以访问(在VM系统中分配并且设置了正确的位),而不用于其他任何内容。如果malloc
在无法访问的页面之前找到一些字节,这可能都会改变;或者如果您转到使用尾随空间进行簿记的malloc
实现。
所以这不太安全。
答案 2 :(得分:1)
访问未分配的内存会导致未定义的行为。究竟发生了什么将取决于各种条件。它现在可能“有效”,但在扩展程序时可能会出现问题。
如果您不知道要阅读的项目数量,可以使用几种策略。
答案 3 :(得分:0)
绝对是肯定的。它只是纯粹的运气,你可以访问而无需分配。 malloc
没有你正在使用的记忆,这可能会导致严重的问题。
因此它的强制性(我不想在这里使用更好的词)根据您的需要分配内存然后使用它。
可能导致的一些问题是:
并且当行为未定义时,它可能会让您头疼几个小时。 例如:崩溃的位置可能不是问题的确切原因。
答案 4 :(得分:0)
这段代码的工作原理是内核永远不会给你一小部分系统页面大小(应该是4k)。这意味着第一个sizeof(int)字节之后的内存实际上由您运行的进程拥有,但不是由第二层抽象(malloc)分配给您。
&#34;分段错误&#34;当您尝试访问内核分配给您的页面之外的内存时发生。在你离开你的页面之前,你不会看到它。
这里可能出现的问题是你再次使用malloc,你将收到一个指向你使用的内存的指针,而malloc并没有意识到它。这将导致地狱般的错误,因为您将在不知情的情况下更改在不同上下文中使用的数据。
关于你的第二个问题,正确的方法取决于程序。
如果元素的数量可以合理限制,则可以使用程序中定义的常量始终分配相同的大小。这始终是安全的方式(您需要确保不要让用户给您超过您分配的内容)。
如果你真的有这么多的数组大小,你可能想要使用一个完全为它构建的链表。
答案 5 :(得分:0)
通常会有两种级别的内存分配。在操作系统级别,您将内存页面映射到地址空间。页面是内存管理的基本单位,通常类似于1K或4K字节(但可以更大或小到512字节,具体取决于系统)。通过进行适当的系统调用,可以自己进行映射。但是,应用程序通常只在需要大块内存时才这样做。
标准库通常维护一个页面池。当您调用malloc时,库会查看池中是否有可用内存。如果是这样,它将从操作系统已映射的页面返回一块内存。如果没有,则库进行系统调用以将更多页面映射到进程并将它们添加到托管池。
映射和取消映射页面是一个相当耗时的过程。通过使用池,库可以显着加快速度。
不变,标准库函数在malloc等返回的内存前面分配几个字节,这样当它们空闲时它们就可以知道块中有多少内存。许多人还会添加内存添加块的结尾以及错误检查。
当你正在做你正在做的事情时,你可能正在阅读这些额外的数据,或者你可能正在读取由库映射到内存池的一些数据。
你在做什么是不好的。
如果您事先不知道项目数,可以使用数据结构,例如链接列表,其中每个新编号都会创建新条目。