• No results found

Memory management functions

7. Library

7.20 General Utilities <stdlib.h>

7.20.3 Memory management functions

The treatment of null pointers and zero-length allocation requests in the definition of these 20

functions was in part guided by a desire to support this paradigm: OBJ * p; // pointer to a variable list of OBJs

/* initial allocation */

p = (OBJ *) calloc(0, sizeof(OBJ)); /* ... */

25

/* reallocations until size settles */ while(1) {

p = (OBJ *) realloc((void *)p, c * sizeof(OBJ)); /* change value of c or break out of loop */

} 30

This coding style, not necessarily endorsed by the Committee, is reported to be in widespread use.

Some implementations have returned non-null values for allocation requests of zero bytes. Although this strategy has the theoretical advantage of distinguishing between “nothing” and “zero” (an unallocated pointer vs. a pointer to zero-length space), it has the more compelling 35

cannot be declared, the only way they could come into existence would be through such allocation requests.

The C89 Committee decided not to accept the idea of zero-length objects. The allocation functions may therefore return a null pointer for an allocation request of zero bytes. Note that this treatment does not preclude the paradigm outlined above.

5

QUIET CHANGE IN C89

A program which relies on size-zero allocation requests returning a non-null pointer will behave differently.

Some implementations provide a function, often called alloca, which allocates the requested object from automatic storage; and the object is automatically freed when the calling function 10

exits. Such a function is not efficiently implementable in a variety of environments, so it was not adopted in the Standard.

7.20.3.1 The calloc function

Both nelem and elsize must be of type size_t for reasons similar to those for fread (see §7.19.8.1).

15

If a scalar with all bits zero is not interpreted as a zero value by an implementation, then calloc may have astonishing results in existing programs transported there.

7.20.3.2 The free function

The Standard makes clear that a program may only free that which has been allocated, that an allocation may only be freed once, and that a region may not be accessed once it is freed. Some 20

implementations allow more dangerous license. The null pointer is specified as a valid argument to this function to reduce the need for special-case coding.

7.20.3.4 The realloc function

A null first argument is permissible. If the first argument is not null, and the second argument is 0, then the call frees the memory pointed to by the first argument, and a null argument may be 25

returned; C99 is consistent with the policy of not allowing zero-sized objects.

A new feature of C99: the realloc function was changed to make it clear that the pointed-to object is deallocated, a new object is allocated, and the content of the new object is the same as that of the old object up to the lesser of the two sizes. C89 attempted to specify that the new object was the same object as the old object but might have a different address. This conflicts 30

with other parts of the Standard that assume that the address of an object is constant during its lifetime. Also, implementations that support an actual allocation when the size is zero do not necessarily return a null pointer for this case. C89 appeared to require a null return value, and the Committee felt that this was too restrictive.

7.20.4 Communication with the environment

7.20.4.1 The abort function

The C89 Committee vacillated over whether a call to abort should return if the SIGABRT signal is caught or ignored. To minimize astonishment, the final decision was that abort never returns.

5

7.20.4.2 The atexit function

atexit provides a program with a convenient way to clean up the environment before it exits. It was adapted from the Whitesmiths C run-time library function onexit.

A suggested alternative was to use the SIGTERM facility of the signal/raise machinery, but that would not give the last-in-first-out stacking of multiple functions so useful with atexit. 10

In C90, it was not clear what should happen if atexit were called after exit; the specification was impossible to meet in that case since the newly-registered function would have to be called before the function that registered it! The committee ruled that calling atexit after exit resulted in undefined behavior and existing implementations exhibited a number of different behaviors: registering the function and calling it as soon as possible (in other words, behaving as 15

though registering a function pushes it onto the top of a stack and exit pops the top function off the stack and calls it until the stack is empty), registering the function but never calling it, failing to register the function, and crashing.

New feature of C99: In C99, the committee was persuaded that there were legitimate reasons for calling atexit after exit (for example, a third-party library routine has no way to know 20

whether it is being called from an exit handler or not) and thus undefined behavior was not appropriate. The committee decided to revise the specification to indicate that stack-like behavior is preferred, although implementations where that is difficult are still free to have atexit fail when called after exit. The other behaviors are no longer permissible, however.

7.20.4.3 The exit function

25

The argument to exit is a status indication returned to the invoking environment. In the UNIX operating system, a value of zero is the successful return code from a program. As usage of C has spread beyond UNIX, exit(0) has often been retained as an idiom indicating successful termination, even on operating systems with different systems of return codes. This usage is thus recognized as standard. There has never been a portable way of indicating a non-successful 30

termination, since the arguments to exit are implementation-defined. The EXIT_FAILURE macro was added to C89 to provide such a capability. EXIT_SUCCESS was added as well. Aside from calls explicitly coded by a programmer, exit is invoked on return from main. Thus in at least this case, the body of exit cannot assume the existence of any objects with automatic storage duration except those declared in exit.

The Committee considered the addition of _exit, but rejected it based on concerns of incompatible with the POSIX specification upon which it is based. For example, one concern expressed is that _exit was specified as a way to get out of a signal handler without triggering another signal, but that is not actually the way _exit behaves in POSIX environments. The Committee did not wish to give programmers this kind of false hope. (But see §7.20.4.4 for 5

C99.)

7.20.4.4 The _Exit function

A new feature of C99: the C99 Committee considered it desirable to have an _exit-like function that would result in immediate program termination without triggering signals or atexit-registered functions, but chose the name, _Exit, rather than _exit, because of the 10

potential conflict with existing practice mentioned above.

7.20.4.5 The getenv function

The definition of getenv is designed to accommodate both implementations that have all in-memory read-only environment strings and those that may have to read an environment string into a static buffer. Hence the pointer returned by the getenv function points to a string not 15

modifiable by the caller. If an attempt is made to change this string, the behavior of future calls to getenv are undefined.

A corresponding putenv function was omitted from the Standard, since its utility outside a multi-process environment is questionable, and since its definition is properly the domain of an operating system standard.

20

7.20.4.6 The system function

The system function allows a program to suspend its execution temporarily in order to run another program to completion.

Information may be passed to the called program in three ways: through command-line argument strings, through the environment, and (most portably) through data files. Before 25

calling the system function, the calling program should close all such data files.

Information may be returned from the called program in two ways: through the implementation- defined return value (In many implementations, the termination status code which is the

argument to the exit function is returned by the implementation to the caller as the value returned by the system function.), and (most portably) through data files.

30

If the environment is interactive, information may also be exchanged with users of interactive devices. Some implementations offer built-in programs called “commands” (for example, “date”) which may provide useful information to an application program via the system function. The Standard does not attempt to characterize such commands, and their use is not portable.

On the other hand, the use of the system function is portable, provided the implementation supports the capability. The Standard permits the application to ascertain this by calling the system function with a null pointer argument. Whether more levels of nesting are supported can also be ascertained this way; but assuming more than one such level is obviously dangerous.