Malloc - >分配了多少内存?

Pen*_*rce 7 c malloc memory-management

# include <stdio.h>
# include <stdbool.h>
# include <string.h>
# include <stdlib.h>

int main ()
{
  char * buffer;
  buffer = malloc (2);

  if (buffer == NULL){
    printf("big errors");
  }
  strcpy(buffer, "hello");
  printf("buffer is %s\n", buffer);
  free(buffer);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我为指针/ char分配了2个字节的内存,buffer但是如果我hello为它分配C风格的字符串,它仍会打印整个字符串,而不会给我任何错误.为什么编译器没有给我一个错误告诉我没有足够的内存分配?我读了几个问题,询问如何检查malloc实际分配的内存量,但我找不到具体的答案.该free函数不应该确切地知道分配了多少内存buffer

bma*_*ies 14

编译器不知道.这是C. malloc属于运行时的喜悦和恐惧.所有的编译器都知道你告诉它它返回一个void*,它不知道strcpy要复制多少,或多少.

像valgrind这样的工具可以检测到其中的一些错误.其他编程语言让你更难以自己拍摄.不是C.

  • 但是在其他语言中,当你*用脚射击自己时,它会把你的整条腿吹走! (2认同)

小智 5

任何生产malloc()实现都不应阻止您尝试写入超出分配的内容。假设如果您分配 123 字节,您将使用所分配的全部或更少的字节。malloc()为了提高效率,必须假设程序员将跟踪他们的指针。

使用您没有明确且成功地要求malloc()提供给您的记忆是未定义的行为。由于字节对齐的实现优化,您可能要求n个字节,但得到n + x 。malloc()或者你可能正在写一个黑洞。你永远无法知道,这就是为什么它是未定义的行为。

话虽如此 ...

有一些malloc()实现可以为您提供内置的统计和调试功能,但是这些需要用来代替标准malloc()设施,就像您使用垃圾收集品种一样。

我还看到了严格为 LD_PRELOAD 设计的变体,它们公开了一个函数,允许您定义至少一个 void 指针作为参数的回调。该论证需要一个包含统计数据的结构。其他工具(例如电围栏)只会按照导致溢出或访问无效块的确切指令停止程序。正如 @R.. 在评论中指出的那样,这对于调试来说非常有用,但效率非常低。

老实说,或者(正如他们所说)“最终”——在这种情况下,使用诸如Valgrind之类的堆分析器及其相关工具(massif)要容易得多,这将为您提供相当多的信息。在这种特殊情况下,Valgrind 会指出显而易见的事情 - 你写的超出了分配的边界。然而,在大多数情况下,当这不是故意的时,一个好的分析器/错误检测器是无价的。

由于以下原因,并不总是可以使用探查器:

  • 在探查器下运行时出现计时问题(但这些问题在malloc()拦截调用时很常见)。
  • Profiler 不适用于您的平台/架构
  • 调试数据(来自日志记录malloc())必须是程序的组成部分

我们使用了我在 HelenOS 中链接的库的一个变体(我不确定他们是否仍在使用它)很长一段时间,因为众所周知,在 VMM 上进行调试会导致疯狂。

尽管如此,在考虑减少更换时,请认真考虑未来的影响,当涉及到设施时,malloc()您几乎总是希望使用系统附带的东西。