这是我的代码(它是必须 纯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(字节)时,它可以工作。
我不确定如何分配"更大"像我的例子中的内存块?
修改:阅读评论后,以下是一些说明:
malloc
和memset
使用相同的buffSize
具有相同的行为。sizeof(size_t) == 2
sizeof(unsigned long) == 4
所以它是16位。因此,在16位系统下,如何创建一个64 KB零填充的char *
?
答案 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_MAX
是size_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