Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

are "too large" objects with automatic storage duration undefined behaviour?

A recent question on SO concerning "Why does allocating a large element on the stack not fail in this specific case?" and a series of other questions concerning "large arrays on the stack" or "stack size limits" made me search for related limits documented in the standard.

I know that the C standard does not specify a "stack" and that it therefore does not define any limits for such a stack. But I wondered up to which SIZE_X in void foo() { char anArray[SIZE_X]; ... } the standard guarantees the program to work, and what happened if a program exceeded this SIZE_X.

I found the following definition, but I'm not sure if this definition is actually a guarantee for a specific supported size of objects with automatic storage duration (cf. this online C11 standard draft):

5.2.4.1 Translation limits

(1) The implementation shall be able to translate and execute at least one program that contains at least one instance of every one of the following limits:

...

65535 bytes in an object (in a hosted environment only)

Does this mean that an implementation must support a value up to 65535 for SIZE_X in a function like void foo() { char anArray[SIZE_X]; ... } and that any value larger than 65535 for SIZE_X is undefined behaviour?

For the heap, a call to malloc returning NULL let's me control the attempt of requesting "too large objects". But how can I control the behaviour of the program if it "requests a too large object with automatic storage duration", specifically if such a maximum size were not documented, e.g. in some limits.h? So is it possible to write a portable function like checkLimits() supporting an "entry barrier" like:

int main() {
   if(! checkLimits()) {
      printf("program execution for sure not supported in this environment.");     
      return 1;
   } else {
      printf("might work. wish you good luck!"); 
   }
   ...
}
like image 382
Stephan Lechner Avatar asked Nov 09 '17 21:11

Stephan Lechner


People also ask

What is the lifetime of an object with static storage duration?

An object whose identifier is declared without the storage-class specifier _Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.

Does the extern keyword affect the storage duration of variables?

It specifies external linkage, and does not technically affect storage duration, but it cannot be used in a definition of an automatic storage duration object, so all extern objects have static or thread durations. In addition, a variable declaration that uses extern and has no initializer is not a definition.

What is the storage duration of a subobject?

The storage duration of subobjects and reference members is that of their complete object. A name that denotes object, reference, function, type, template, namespace, or value, may have linkage. If a name has linkage, it refers to the same entity as the same name introduced by a declaration in another scope.

What is the lifetime of an object in C++?

Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup. Since its stored value is initialized only once, an object with static storage duration can profile the invocations of a function.


1 Answers

Technically, an implementation only needs to translate and execute one program with a 65,535-byte object (and the other things listed) in order to conform to the standard. It could fail on all others.

To know that larger programs work, you must rely on details of your specific implementation. Most implementations provide for more stack space than 64 KiB, although it may be undocumented. There may be linker switches for adjusting the stack space allowed.

E.g., for the ld linker on current macOS, the default is 8 MiB, and the -stack_size switch can be used to set more or less (for the main thread).

I would say that since the C standard says that environmental limits such as stack space may constrain the implementation, anything other than the fact that one particular sample program must work is technically undefined behavior.

like image 180
Eric Postpischil Avatar answered Sep 24 '22 00:09

Eric Postpischil