为什么当我传递一个" big"时,calloc总是返回NULL。尺寸?

时间:2014-12-10 16:36:34

标签: c malloc calloc

这是我的代码(它是必须 纯C ):

unsigned long buffSize = 65536; /* 64 KB */
char *block;

block = calloc(1, buffSize);
if (block == NULL)
{
    /* This is always triggered */
}

我想要一个64 KB的归零内存,我将在我的应用程序的其他地方的循环中使用。

不幸calloc总是返回NULL。当我使用64(字节)时,它可以工作。

我不确定如何分配"更大"像我的例子中的内存块?

修改:阅读评论后,以下是一些说明:

  1. mallocmemset使用相同的buffSize具有相同的行为。
  2. sizeof(size_t) == 2 sizeof(unsigned long) == 4所以它是16位。
  3. 目标平台是MS-DOS 6.22。
  4. 因此,在16位系统下,如何创建一个64 KB零填充的char *

2 个答案:

答案 0 :(得分:5)

您已经说sizeof (size_t) == 2(这是MS-DOS 6.22)。

这意味着size_t的最大值为65535

unsigned long buffSize = 65536; /* 64 KB */

到目前为止没问题。 unsigned long必须至少为32位(系统上为32位),因此可以轻松保存值65536

char *block;

block = calloc(1, buffSize);

calloc的两个参数都是size_t类型。任何不属于size_t类型的参数都会被隐式转换。将65536转换为size_t会产生0。所以你要求分配0个字节。这种分配的行为是实现定义的;它可以返回一个空指针,或者它可以返回一个唯一的非空指针,类似于malloc(1),除了你不能取消引用它。你的实现显然是前者。

calloc接受两个类型size_t的参数。它们的值不是简单地乘以产生类型size_t的结果。相反,calloc必须成功分配指定的字节数,否则将返回空指针。

原则上,你可以写:

block = calloc(64, 1024);

或类似的东西。如果成功,它将分配65536字节的对象。

但是由于size_t只有16位,这几乎可以肯定意味着实现不能创建大于65535字节的对象。实际上没有禁止创建大于SIZE_MAX字节的对象,但任何能够这样做的实现几乎肯定会使其size_t更大,因此它可以代表任何物体的大小。

SIZE_MAXsize_t类型的最大值。它是<stdint.h>中定义的宏,它是由C99标准引入的。您的实现可能不是&#39} ; t支持<stdint.h>。表达式((size_t)-1)是等效的。)

除非您使用不同的实现(这可能意味着使用具有不同选项的相同编译器),否则您可能会运气不好。

也许您可以重新设计程序,以便它可以使用两个32768字节的对象而不是单个65536字节的对象(尽管可能也不支持)。

MS-DOS系统支持(支持?)多个内存模型,其中一些可能允许您执行您想要的操作。我不知道细节。有关更多信息,请参阅编译器的文档。

答案 1 :(得分:1)

对于16位实模式,您可能需要指定“巨大”模型,该模型使用远指针来支持数组&gt; 65536的大小。紧凑型或大型模型可能有效,使用单个固定段值和变量偏移量来处理65536的缓冲区大小。我不知道您使用的是什么工具集,但是应该有一个命令行参数来指定程序将使用的内存模型。对于Microsoft 16位实模式编译器,参数为/ AH表示大型,/ AC表示紧凑型,/ AL表示大型。

Wiki链接:Intel Memory Models