C standard regarding sizeof overflowing size_t
Asked Answered
I

1

9

Is this undefined behavior? The relevant parts of the standard don't say much.

size_t n = SIZE_MAX / sizeof(double) + 1;
size_t m = sizeof(double[n]);
Intoxicated answered 3/9, 2019 at 3:23 Comment(3)
I'd treat it as undefined by omissionOverprize
If it's not defined by the standard then it's literally undefined behavior, isn't it? Haha.Barrister
gcc rejects sizeof(double[SIZE_MAX]);Overprize
S
6

The C standard does not explicitly state that the size_t type is sufficient for working with the sizes of all objects or types, especially for hypothetical types that are not actually instantiated.

In C 2018 7.19 2, the standard says that size_t “is the unsigned integer type of the result of the sizeof operator”. That tells us about the type size_t but not about the values that may arise during computation. In 5.2.4, the standard recognizes that C implementations necessarily have limits, and that they must break down at various points.

7.19 4 says “The types used for size_t and ptrdiff_t should not have an integer conversion rank greater than that of signed long int unless the implementation supports objects large enough to make this necessary.” This reaffirms our desire that size_t be capable of representing the sizes of all supported objects, particularly since it implies that the existence of an object makes it “necessary” that size_t be able to represent it, but it is not an explicit statement that size_t must do so, nor does it apply to hypothetical types that can be described but not instantiated as objects.

Were we to evaluate n * sizeof(double), we know the result: 6.2.5 9 says “A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.” However, with sizeof(double[n]), it is not completely clear this applies because, although n is unsigned, it is not the direct operand of sizeof, where the computation of a result that cannot be represented occurs. The standard does not explicitly tell us that the result of this sizeof will be reduced in the same way.

Thus, this operation is not covered by the C standard.

Saskatoon answered 3/9, 2019 at 11:41 Comment(5)
According to this reference: "size_t can store the maximum size of a theoretically possible object of any type (including array)."Kandace
@Ayxan: That reference is wrong. I have cited the C standard in my answer, and it is authoritative.Saskatoon
Would it be appropriate to use the well understood phrase 'undefined behaviour' in your conclusion?Katherine
@ryyker: I would be hesitant to use it. As defined by the C standard, “undefined behavior” is absolute; it means the C standard imposes no requirements at all on the behavior. That indeed might be the case for sizeof(double[SIZE_MAX/sizeof(double) + 1]), but I think it is better to regard this as something the C committee neglected to address rather than something the committee decide should be undefined. (Also, I am not sure the phrase is well understood. Many people seem to treat it as behavior you must avoid, but that is inconsistent with many legitimate C extensions.)Saskatoon
"Undefined behavior is otherwise indicated in this International Standard by the words “undefined behavior” or by the omission of any explicit definition of behavior." (C18 4 p2). Otherwise, I think this covers the issue.Intoxicated

© 2022 - 2024 — McMap. All rights reserved.