这是我的代码(它是并且必须是纯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 位的。 - 目标平台是 MS-DOS 6.22。
那么在 16 位系统下,如何创建 64 KB 零填充的char *
?
你说过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 字节。此类分配的行为是实现定义的;它可以返回 null 指针,也可以返回唯一的非 null 指针,类似于 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标准引入。您的实现可能不支持<stdint.h>
。表达式 ((size_t)-1)
是等效的。
你可能不走运,除非你使用不同的实现(这可能意味着使用相同的编译器和不同的选项(。
也许您可以重新设计程序,以便它可以使用两个 32768 字节的对象,而不是单个 65536 字节的对象(尽管也可能不支持(。
MS-DOS 系统支持(支持?(多种内存模型,其中一些可能允许您执行所需的操作。我不知道细节。有关详细信息,请参阅编译器的文档。
对于 16 位实数模式,您可能需要指定"巨大"模型,该模型使用远指针来支持大小> 65536 的数组。紧凑或大型模型可能有效,使用单个固定段值和可变偏移量来处理缓冲区大小 65536。我不知道你正在使用什么工具集,但应该有一个命令行参数来指定程序将使用的内存模型。对于Microsoft 16 位实模式编译器,参数为/AH 表示大型,/AC 表示紧凑,/AL 表示大型。
维基链接: 英特尔内存模型