内存分配问题

时间:2010-12-09 06:15:01

标签: c memory-management

在求职面试的书面回合中提出了这个问题:

 #include<alloc.h>
 #define MAXROW 3
 #define MAXCOL 4

 main()
  {
    int (*p)[MAXCOL];
     p = (int (*)[MAXCOL]) malloc(MAXROW*(sizeof(*p)));
  }

进程中分配了多少字节?

说实话,我没有回答这个问题。我不理解p的作业。

有人可以解释一下答案是什么以及如何推断出来?

10 个答案:

答案 0 :(得分:8)

它取决于平台。

int (*p)[MAXCOL];声明一个指向MAXCOL元素宽整数数组的指针(在这种情况下,MAXCOL当然是4)。因此,该指针的一个元素是目标平台上的4*sizeof(int)

malloc语句分配内存缓冲区MAXROW乘以P中包含的类型的大小。因此,总共分配MAXROW * MAXCOL整数。实际的字节数取决于目标平台。

此外,C运行时可能会使用额外的内存(作为malloc中的内部bookeeping,以及调用main之前发生的各种进程初始化位),这也完全取决于平台。

答案 1 :(得分:7)

p是指向MAXCOL类型的int元素数组的指针,因此sizeof *p(括号是多余的)是这样一个数组的大小,即{ {1}}。

MAXCOL*sizeof(int)的返回值上的强制转换是不必要的,丑陋的,并且被认为是有害的。在这种情况下,它隐藏了一个严重的错误:由于缺少原型,假定malloc隐式返回malloc,这与其正确的返回类型(int)不兼容,因此导致未定义行为。

答案 2 :(得分:6)

sizeof(*p)将为MAXCOL*sizeof(int)。所以分配了MAXROW*MAXCOL*sizeof(int)个字节。

答案 3 :(得分:6)

您可能需要查看cdecl以获取将C声明翻译成英语的帮助。在这种情况下,int (*p)[4];变为declare p as pointer to array 4 of int

答案 4 :(得分:5)

#include<alloc.h>
#define MAXROW 3 
#define MAXCOL 4
main()   {
    int (*p)[MAXCOL];
    p = (int (*)[MAXCOL]) malloc(MAXROW*(sizeof(*p));
}
  

进程中分配了多少字节?

p是一个指针,因此将占用堆栈上的sizeof(int(*)[MAXCOL]),这可能看起来令人生畏但它几乎总是与sizeof(void*)sizeof(int*)或任何其他指针相同。显然,指针大小使应用程序的分类为16,32,64等。位,并且此指针将相应地调整大小。

然后p指向从malloc ...

获得的一些记忆
malloc( MAXROW * sizeof(*p) )

sizeof(*p)int所指向的p数组的大小,即sizeof(int) * MAXCOL,所以我们得到

malloc( MAXROW * (sizeof(int) * MAXCOL) )

从堆请求。为了便于说明,如果我们假设共同的32位int大小,我们将查看48个字节。实际使用情况可以四舍五入到堆例程的感觉(堆例程经常使用固定大小的“桶”来加速它们的操作)。

要确认此期望,只需将记录函数替换为malloc()

#include <stdio.h>

#define MAXROW 3
#define MAXCOL 4

void* our_malloc(size_t n)
{
    printf("malloc(%ld)\n", n);
    return 0;
}

int main()
{
    int (*p)[MAXCOL];
    p = (int (*)[MAXCOL]) our_malloc(MAXROW*(sizeof(*p)));
}

我的Linux机箱输出:

malloc(48)

malloc的返回指针被转换为p的类型的事实不会影响完成的内存分配量。

正如R强烈观察到的那样,缺少malloc原型会导致编译器期望malloc返回int而不是实际返回的void*。实际上,指针中最小的sizeof(int)字节很可能在转换后仍然存在,如果sizeof(void *)碰巧等于sizeof(int),或者 - 更脆弱 - 堆内存恰好开始尽管指针的大小较大(即所有截断的位都是0),但是在int中可表示的地址处,然后稍后解除指针的引用可能会起作用。廉价插件:除非看到原型,否则C ++不会编译。

那也许你的alloc.h包含一个malloc原型......我没有alloc.h所以我猜它是非标准的。

任何程序也会为许多其他事物分配内存,例如提供一些可以调用main()的上下文的堆栈帧。内存量因编译器,版本,编译器标志,操作系统等而异。

答案 5 :(得分:3)

int (*p)[MAXCOL] == int (*p)[4] ==“指向数组4的指针”(见下面的注释)

然后

sizeof(*p)将是p指向的,即4 * sizeof(int)。乘以MAXROW,您的最终答案是:

12 * sizeof(int)

注意:这与:

相反

int *p[MAXCOL] == int *p[4] ==“指向int的指针的数组4”
括号有很大区别!

答案 6 :(得分:3)

它应该是MAXROW * MAXCOL * sizeof(int)字节数

答案 7 :(得分:3)

我真的不喜欢这样的问题,因为我认为作为一名工作工程师来运行实验比假设你知道自己在做什么要好得多 - 特别是如果有理由怀疑某项程序无法按预期工作或有人制作技巧问题。

#include <stdlib.h>
#include <stdio.h>
#define MAXROW 3
#define MAXCOL 4

main()
{
  int (*p)[MAXCOL];
  int bytes = MAXROW * (sizeof(*p));
  p = (int (*)[MAXCOL]) malloc(bytes);
  printf("malloc called for %d bytes\n", bytes);
}

在32位Linux系统上:

gcc test.c
./a.out
malloc调用了48个字节

(编辑删除乘以maxrow两次的粘贴事故,产生错误的144字节大小)

答案 8 :(得分:1)

在codepad.org中运行以下内容:

//#include<alloc.h>
#define MAXROW 3
#define MAXCOL 4

int main()
{
    int (*p)[MAXCOL];
    p = (int (*)[MAXCOL]) malloc(MAXROW*(sizeof(*p)));

    int x = MAXROW*(sizeof(*p));
    printf("%d", x);

    return 0;
}

打印出48。

为什么呢?由于MAXROW为3,sizeof(*p)为16,因此我们得到3 * 16。

为什么sizeof(*p) 16?因为MAXCOL是4,所以p是指向4个int的数组的指针。每个int是32位= 4个字节。数组中的4个整数* 4个字节= 16。

为什么sizeof(*p)不是4?因为它是p指向的大小,而不是p的大小。要成为p的大小,它必须是sizeof(p),这将是4,因为p是一个指针。

迂腐地说,你可以补充一下:

  1. 如果机器是64位(比方说),答案是96。
  2. 问题是“在进程中分配了多少字节?”,您需要为指针p添加4个字节。
  3. malloc可以分配比你要求的更多(但不能少),所以这个问题无法回答。
  4. 与2类似,您可以争辩说,由于进程也在加载系统dll(如C运行时dll)以便运行,因此它也为这些进行了分配空间。然后你可以争论由其他(非系统)进程注入到进程中的dll分配的空间,例如由Actual Window Manager及其类似注入的进程。但是我们想要得到多么迂腐?
  5. 但我认为问题实际上是要求48,可能会有额外的功劳来解释96。

答案 9 :(得分:0)

零字节怎么样,因为如果没有非标准的alloc.h,它甚至都不能编译。如果你无法编译它,你就无法运行它,如果你不能运行它,它根本就不能分配任何内存。