为什么数组的最大大小“太大”? [英] Why is the maximum size of an array "too large"?

查看:332
本文介绍了为什么数组的最大大小“太大”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我和这个回答的印象一样, size_t 总是由标准保证足够大以保存给定系统的最大可能类型。

然而,这段代码无法在gcc / Mingw上编译:

  #include  
#include< stddef.h>

typedef uint8_t array_t [SIZE_MAX];




error:array'array_t'的大小太大


我误解了标准中的某些内容吗?对于给定的实现,是否允许 size_t 过大?或者这是Mingw的另一个bug?






编辑:进一步的研究表明,

  typedef uint8_t array_t [SIZE_MAX / 2]; //不会编译
typedef uint8_t array_t [SIZE_MAX / 2 + 1]; //不会编译

这恰好与

相同

  #include< limits.h> 

typedef uint8_t array_t [LLONG_MAX]; //不会编译
typedef uint8_t array_t [LLONG_MAX +(size_t)1]; //不会编译

所以我现在倾向于认为这是Mingw中的一个bug,因为根据有符号整数类型设置允许的最大大小没有任何意义。

解决方案

限制SIZE_MAX / 2从你的实现中的size_t和ptrdiff_t的定义中选择,类型ptrdiff_t和size_t具有相同的宽度。



C标准要求 1 该类型的size_t是无符号的,并且类型ptrdiff_t是带符号的。

两个指针之间的差异结果总是 2 具有类型ptrdiff_t。这意味着,在您的实现中,对象的大小必须限制为
PTRDIFF_MAX,否则两个指针的有效差异不能用ptrdiff_t类型表示,导致未定义的行为。



因此,值SIZE_MAX / 2等于值PTRDIFF_MAX。如果实现选择使最大对象大小为SIZE_MAX,则类型ptrdiff_t的宽度将不得不增加。但是将对象的最大尺寸限制为SIZE_MAX / 2要容易得多,然后就是让类型ptrdiff_t具有比类型size_t更大或相等的正范围。



标准在主题上提供了 3 评论
b
b

(引自ISO / IEC 9899:201x)

1 (7.19通用定义2)

类型是

ptrdiff_t

这是减去两个指针的结果的有符号整数类型;

size_t

这是sizeof运算符结果的无符号整数类型;

2 (6.5.6添加运算符9)

当减去两个指针,它们都应指向同一个数组对象的元素
或一个超过数组对象的最后一个元素;结果是两个数组元素的
下标的差异。结果的大小是实现定义的
,它的类型(一个有符号整数类型)是在头文件中定义的ptrdiff_t。
如果结果在该类型的对象中不可表示,则行为未定义。



3 (K.3.4整型类型3)

极大的对象大小通常表示对象的大小计算错误
。例如,当
转换为像size_t这样的无符号类型时,负数显示为非常大的正数。另外,有些实现不支持
对象,它的大小可以用size_t类型表示的最大值。 K.3.4整数类型4)

由于这些原因,限制对象大小的范围以检测
编程错误有时是有益的。对于具有大地址空间的机器实现
,建议将RSIZE_MAX定义为支持的最大
对象或(SIZE_MAX >> 1)的较小值,即使此限制小于
的大小是一些合法但非常大的对象。针对具有小
地址空间的机器的实现可能希望将RSIZE_MAX定义为SIZE_MAX,这意味着不存在被视为运行时约束违规的对象大小。


I'm under the same impression as this answer, that size_t is always guaranteed by the standard to be large enough to hold the largest possible type of a given system.

However, this code fails to compile on gcc/Mingw:

#include <stdint.h>
#include <stddef.h>

typedef uint8_t array_t [SIZE_MAX];

error: size of array 'array_t' is too large

Am I misunderstanding something in the standard here? Is size_t allowed to be too large for a given implementation? Or is this another bug in Mingw?


EDIT: further research shows that

typedef uint8_t array_t [SIZE_MAX/2];   // does compile
typedef uint8_t array_t [SIZE_MAX/2+1]; // does not compile

Which happens to be the same as

#include <limits.h>

typedef uint8_t array_t [LLONG_MAX];           // does compile
typedef uint8_t array_t [LLONG_MAX+(size_t)1]; // does not compile

So I'm now inclined to believe that this is a bug in Mingw, because setting the maximum allowed size based on a signed integer type doesn't make any sense.

解决方案

The limit SIZE_MAX / 2 comes from the definitions of size_t and ptrdiff_t on your implementation, which choose that the types ptrdiff_t and size_t have the same width.

C Standard mandates1 that type size_t is unsigned and type ptrdiff_t is signed.

The result of difference between two pointers, will always2 have the type ptrdiff_t. This means that, on your implementation, the size of the object must be limited to PTRDIFF_MAX, otherwise a valid difference of two pointers could not be represented in type ptrdiff_t, leading to undefined behavior.

Thus the value SIZE_MAX / 2 equals the value PTRDIFF_MAX. If the implementation choose to have the maximum object size be SIZE_MAX, then the width of the type ptrdiff_t would have to be increased. But it is much easier to limit the maximum size of the object to SIZE_MAX / 2, then it is to have the type ptrdiff_t have a greater or equal positive range than that of type size_t.

Standard offers these3 comments4 on the topic.


(Quoted from ISO/IEC 9899:201x)

1 (7.19 Common definitions 2)
The types are
ptrdiff_t
which is the signed integer type of the result of subtracting two pointers;
size_t
which is the unsigned integer type of the result of the sizeof operator;

2 (6.5.6 Additive operators 9)
When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the header. If the result is not representable in an object of that type, the behavior is undefined.

3 (K.3.4 Integer types 3)
Extremely large object sizes are frequently a sign that an object’s size was calculated incorrectly. For example, negative numbers appear as very large positive numbers when converted to an unsigned type like size_t. Also, some implementations do not support objects as large as the maximum value that can be represented by type size_t.

4 (K.3.4 Integer types 4)
For those reasons, it is sometimes beneficial to restrict the range of object sizes to detect programming errors. For implementations targeting machines with large address spaces, it is recommended that RSIZE_MAX be defined as the smaller of the size of the largest object supported or (SIZE_MAX >> 1), even if this limit is smaller than the size of some legitimate, but very large, objects. Implementations targeting machines with small address spaces may wish to define RSIZE_MAX as SIZE_MAX, which means that there is no object size that is considered a runtime-constraint violation.

这篇关于为什么数组的最大大小“太大”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆