首页 文章

没有用c语言分配访问内存空间有什么问题[重复]

提问于
浏览
-2

这个问题在这里已有答案:

#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

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

  • 1

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

    所以这不是很安全 .

  • 0

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

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

    • 使用realloc增加缓冲区,因为您需要更多空间 .

    • 使用链接列表而不是数组

  • 0

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

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

    可能导致的一些问题是:

    • 分段错误

    • 内存损坏

    当行为未定义时,它可能会让你头疼几个小时 . 例如:崩溃的位置可能不是问题的确切原因 .

  • 8

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

    当您尝试访问内核分配给您的页面之外的内存时,会发生“分段错误” . 在你走出你的页面之前,你不会看到它 .

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

    至于你的第二个问题,正确的方法是非常依赖程序的 .

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

    如果您确实在这里拥有广泛的数组大小,则可能需要使用专为此构建的链接列表 .

  • 3

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

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

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

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

    当您正在执行您正在执行的操作时,您可能正在读取此额外数据,或者您可能正在读取由库映射到内存池的某些数据 .

    你做的很糟糕 .

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

相关问题