没有在c语言中分配,访问内存空间是否有任何问题

时间:2010-08-19 06:34:00

标签: c memory-management


#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程序中,内存是在没有分配的情况下访问的。程序可以工作。如果没有分配就访问内存会出现什么问题?如果是,那么存储大小未提前知道的整数数据集合的解决方案是什么?

6 个答案:

答案 0 :(得分:8)

是的,它会导致未定义的行为。问题是工作这里纯粹是因为运气而且可能随时崩溃。解决方案是使用malloc分配内存。例如,如果要为count个元素分配内存,则可以使用int* p = (int*)malloc(sizeof(int)*count);。从这里开始,您可以访问p作为count元素的数组。

答案 1 :(得分:3)

它可能有效,因为*p之后的内存都可以访问(在VM系统中分配并且设置了正确的位),而不用于其他任何内容。如果malloc在无法访问的页面之前找到一些字节,这可能都会改变;或者如果您转到使用尾随空间进行簿记的malloc实现。

所以这不太安全。

答案 2 :(得分:1)

访问未分配的内存会导致未定义的行为。究竟发生了什么将取决于各种条件。它现在可能“有效”,但在扩展程序时可能会出现问题。

如果您不知道要阅读的项目数量,可以使用几种策略。

  1. 当您需要更多空间时,请使用realloc来扩展缓冲区。
  2. 使用链接列表而不是数组

答案 3 :(得分:0)

绝对是肯定的。它只是纯粹的运气,你可以访问而无需分配。 malloc没有你正在使用的记忆,这可能会导致严重的问题。

因此它的强制性(我不想在这里使用更好的词)根据您的需要分配内存然后使用它。

可能导致的一些问题是:

  1. 分段错误
  2. 内存损坏
  3. 并且当行为未定义时,它可能会让您头疼几个小时。 例如:崩溃的位置可能不是问题的确切原因。

答案 4 :(得分:0)

这段代码的工作原理是内核永远不会给你一小部分系统页面大小(应该是4k)。这意味着第一个sizeof(int)字节之后的内存实际上由您运行的进程拥有,但不是由第二层抽象(malloc)分配给您。

&#34;分段错误&#34;当您尝试访问内核分配给您的页面之外的内存时发生。在你离开你的页面之前,你不会看到它。

这里可能出现的问题是你再次使用malloc,你将收到一个指向你使用的内存的指针,而malloc并没有意识到它。这将导致地狱般的错误,因为您将在不知情的情况下更改在不同上下文中使用的数据。

关于你的第二个问题,正确的方法取决于程序。

如果元素的数量可以合理限制,则可以使用程序中定义的常量始终分配相同的大小。这始终是安全的方式(您需要确保不要让用户给您超过您分配的内容)。

如果你真的有这么多的数组大小,你可能想要使用一个完全为它构建的链表。

答案 5 :(得分:0)

通常会有两种级别的内存分配。在操作系统级别,您将内存页面映射到地址空间。页面是内存管理的基本单位,通常类似于1K或4K字节(但可以更大或小到512字节,具体取决于系统)。通过进行适当的系统调用,可以自己进行映射。但是,应用程序通常只在需要大块内存时才这样做。

标准库通常维护一个页面池。当您调用malloc时,库会查看池中是否有可用内存。如果是这样,它将从操作系统已映射的页面返回一块内存。如果没有,则库进行系统调用以将更多页面映射到进程并将它们添加到托管池。

映射和取消映射页面是一个相当耗时的过程。通过使用池,库可以显着加快速度。

不变,标准库函数在malloc等返回的内存前面分配几个字节,这样当它们空闲时它们就可以知道块中有多少内存。许多人还会添加内存添加块的结尾以及错误检查。

当你正在做你正在做的事情时,你可能正在阅读这些额外的数据,或者你可能正在读取由库映射到内存池的一些数据。

你在做什么是不好的。

如果您事先不知道项目数,可以使用数据结构,例如链接列表,其中每个新编号都会创建新条目。