7. Memory Allocation

comp.lang.c FAQ list · Question 7.1

Q: Why doesn't this fragment work?

	char *answer;
	printf("Type something:\n");

A: The pointer variable answer, which is handed to gets() as the location into which the response should be stored, has not been set to point to any valid storage. It is an uninitialized variable, just as is the variable i in

	int i;
That is, in the first piece of code, we cannot say where the pointer answer points, just as we cannot say what value i will have in the second. (Since local variables are not initialized, and typically contain garbage, it is not even guaranteed that answer starts out as a null pointer. See questions 1.30 and 5.1.)

The simplest way to correct the question-asking program is to use a local array, instead of a pointer, and let the compiler worry about allocation:

#include <stdio.h>
#include <string.h>

char answer[100], *p;
printf("Type something:\n");
fgets(answer, sizeof answer, stdin);
	*p = '\0';

This example also uses fgets() instead of gets(), so that the end of the array cannot be overwritten. (See question 12.23. Unfortunately for this example, fgets() does not automatically delete the trailing \n, as gets() would.) It would also be possible to use malloc() to allocate the answer buffer, and to parameterize the buffer size (with something like #define ANSWERSIZE 100 ).

comp.lang.c FAQ list · Question 7.2

Q: I can't get strcat to work. I tried

	char *s1 = "Hello, ";
	char *s2 = "world!";
	char *s3 = strcat(s1, s2);
but I got strange results.

A: As in question 7.1, the main problem here is that space for the concatenated result is not properly allocated. C does not provide an automatically-managed string type. C compilers allocate memory only for objects explicitly mentioned in the source code (in the case of strings, this includes character arrays and string literals). The programmer must arrange for sufficient space for the results of run-time operations such as string concatenation, typically by declaring arrays, or by calling malloc.

strcat performs no allocation; the second string is appended to the first one, in place. The first (destination) string must be writable and have enough room for the concatenated result. Therefore, one fix would be to declare the first string as an array:

	char s1[20] = "Hello, ";
(In production code, of course, we wouldn't use magic numbers like ``20''; we'd use more robust mechanisms to guarantee sufficient space.)

Since strcat returns the value of its first argument (s1, in this case), the variable s3 in the question above is superfluous; after the call to strcat, s1 contains the result.

The original call to strcat in the question actually has two problems: the string literal pointed to by s1, besides not being big enough for any concatenated text, is not necessarily writable at all. See question 1.32.

References: CT&P Sec. 3.2 p. 32

comp.lang.c FAQ list · Question 7.3


A: In general, when using pointers you always have to consider memory allocation, if only to make sure that the compiler is doing it for you. If a library function's documentation does not explicitly mention allocation, it is usually the caller's problem.

The Synopsis section at the top of a Unix-style man page or in the ANSI C standard can be misleading. The code fragments presented there are closer to the function definitions used by an implementor than the invocations used by the caller. In particular, many functions which accept pointers (e.g. to structures or strings) are usually called with a pointer to some object (a structure, or an array--see questions 6.3 and 6.4) which the caller has allocated. Other common examples are time (see question 13.12) and stat.

comp.lang.c FAQ list · Question 7.3b

Q: I just tried the code

char *p;
strcpy(p, "abc");
and it worked. How? Why didn't it crash?

A: You got lucky, I guess. The memory randomly pointed to by the uninitialized pointer p happened to be writable by you, and apparently was not already in use for anything vital. See also question 11.35.

Additional links: longer explanation, another longer explanation

comp.lang.c FAQ list · Question 7.3c

Q: How much memory does a pointer variable allocate?

A: That's a pretty misleading question. When you declare a pointer variable, as in

	char *p;
you (or, more properly, the compiler) have allocated only enough memory to hold the pointer itself; that is, in this case you have allocated sizeof(char *) bytes of memory. But you have not yet allocated any memory for the pointer to point to. See also questions 7.1 and 7.2.

comp.lang.c FAQ list · Question 7.4

Q: I'm reading lines from a file into an array, with this code:

	char linebuf[80];
	char *lines[100];
	int i;

		if(p == NULL) break;
		lines[i] = p;

A: You have only allocated memory for one line, linebuf. Each time you call fgets, the previous line is overwritten. fgets doesn't do any memory allocation: unless it reaches EOF (or encounters an error), the pointer it returns is the same pointer you handed it as its first argument (in this case, a pointer to your single linebuf array).

To make code like this work, you'll need to allocate memory for each line. See question 20.2 for an example.

References: K&R1 Sec. 7.8 p. 155
K&R2 Sec. 7.7 pp. 164-5
ISO Sec.
H&S Sec. 15.7 p. 356

comp.lang.c FAQ list · Question 7.5a


A: Whenever a function returns a pointer, make sure that the pointed-to memory is properly allocated. For example, make sure you have not done something like

#include <stdio.h>
char *itoa(int n) { char retbuf[20]; /* WRONG */ sprintf(retbuf, "%d", n); return retbuf; /* WRONG */ }
When a function returns, its automatic, local variables are discarded, so the returned pointer in this case is invalid (it points to an array that no longer exists).

One fix would be to declare the return buffer as

		static char retbuf[20];
This fix is imperfect, since a function using static data is not reentrant. Furthermore, successive calls to this version of itoa keep overwriting the same return buffer: the caller won't be able to call it several times and keep all the return values around simultaneously.

See also questions 7.5b, 12.21, and 20.1.

References: ISO Sec.

comp.lang.c FAQ list · Question 7.5b

Q: So what's the right way to return a string or other aggregate?

A: The returned pointer should be to a statically-allocated buffer (as in the answer to question 7.5a), or to a buffer passed in by the caller, or to memory obtained with malloc, but not to a local (automatic) array.

For example, to have the caller pass space for the result:

	char *itoa(int n, char *retbuf)
		sprintf(retbuf, "%d", n);
		return retbuf;


	char str[20];
	itoa(123, str);

To use malloc:

	#include <stdlib.h>

	char *itoa(int n)
		char *retbuf = malloc(20);
		if(retbuf != NULL)
			sprintf(retbuf, "%d", n);
		return retbuf;


	char *str = itoa(123);
(In this last case, the caller must remember to free the returned pointer when it is no longer needed.)

See also question 20.1.

Additional links: further reading

comp.lang.c FAQ list · Question 7.6


A: Have you #included <stdlib.h>, or otherwise arranged for malloc to be declared properly? If not, the compiler assumes that it returns an int (see question 1.25), which is not correct. (The same problem could arise for calloc or realloc.) See also question 7.15.

References: H&S Sec. 4.7 p. 101

comp.lang.c FAQ list · Question 7.7


A: Before ANSI/ISO Standard C introduced the void * generic pointer type, these casts were typically required to silence warnings (and perhaps induce conversions) when assigning between incompatible pointer types.

Under ANSI/ISO Standard C, these casts are no longer necessary. It can also be argued that they are now to be discouraged; see question 7.7b. Furthermore, well-defined, low-risk implicit conversions (such as those which C has always performed between integer and floating-point types) can be considered a feature.

On the other hand, some programmers prefer to make every conversion explicit, to record that they have considered each case and decided exactly what should happen (see also question 17.5). Also, the casts are typically seen in C code which for one reason or another is intended to be compatible with C++, where explicit casts from void * are required.

(By the way, the language in sections 6.5 and 7.8.5 of K&R2 which suggests that the casts are required is ``overenthusiastic.'')

To some extent, whether you use these casts or not is a matter of style; see section 17.

Additional links: further explanation by Mark Brader


comp.lang.c FAQ list · Question 7.7b

Q: What's wrong with casting malloc's return value?


	char *p = malloc(10);


comp.lang.c FAQ list · Question 7.7c


A: It means you're using a C++ compiler instead of a C compiler. See question 7.7.

comp.lang.c FAQ list · Question 7.8

Q: I see code like

	strcpy(p, s);

A: It's never necessary to multiply by sizeof(char), since sizeof(char) is, by definition, exactly 1. (On the other hand, multiplying by sizeof(char) doesn't hurt, and in some circumstances may help by introducing a size_t into the expression; see question 7.15.) See also questions 8.9 and 8.10.

References: ISO Sec.
H&S Sec. 7.5.2 p. 195

comp.lang.c FAQ list · Question 7.9

Q: I wrote a little wrapper around malloc, but it doesn't work:

	#include <stdio.h>
	#include <stdlib.h>

	mymalloc(void *retp, size_t size)
		retp = malloc(size);
		if(retp == NULL) {

A: See question 4.8. (In this case, you'll want to have mymalloc return the malloc'ed pointer.)

comp.lang.c FAQ list · Question 7.10


char *p;
*p = malloc(10);

A: See question 4.2.

comp.lang.c FAQ list · Question 7.10a

Q: What's wrong with this initialization?

char *p = malloc(10);

A: See question 1.31b.

comp.lang.c FAQ list · Question 7.10b


A: See question 18.5.

comp.lang.c FAQ list · Question 7.11

Q: How can I dynamically allocate arrays?

A: See questions 6.14 and 6.16.

comp.lang.c FAQ list · Question 7.12

Q: How can I find out how much memory is available?

A: See question 19.22.

comp.lang.c FAQ list · Question 7.13


A: See question 11.26.

comp.lang.c FAQ list · Question 7.14


A: It's hard to say. The Standard doesn't say that systems can act this way, but it doesn't explicitly say that they can't, either. (Such a ``deferred failure'' implementation would not seem to conform to the implied requirements of the Standard.)

The conspicuous problem is that, by the time the program gets around to trying to use the memory, there might not be any. The program in this case must typically be killed by the operating system, since the semantics of C provide no recourse. (Obviously, malloc is supposed to return a null pointer if there's no memory, so that the program--as long as it checks malloc's return value at all--never tries to use more memory than is available.)

Systems that do this ``lazy allocation'' usually provide extra signals indicating that memory is dangerously low, but portable or naïve programs won't catch them. Some systems that do lazy allocation also provide a way to turn it off (reverting to traditional malloc semantics), on a per-process or per-user basis, but the details vary from system to system.

Additional links: A longer explanation of the tradeoffs concerning ``lazy allocation''

References: ISO Sec. 7.10.3

comp.lang.c FAQ list · Question 7.15

Q: malloc is returning crazy pointer values, but I did read question 7.6 and I have included the line

	extern void *malloc();
before I call it.


In general, it is much, much safer to declare standard library functions by #including the appropriate header files, rather than typing extern declarations yourself. See also question 7.16.


References: ISO Sec. 7.1.6, Sec. 7.1.7

comp.lang.c FAQ list · Question 7.16

Q: I'm allocating a large array for some numeric work, using the line


A: Notice that 300 x 300 is 90,000, which will not fit in a 16-bit int, even before you multiply it by sizeof(double). If you need to allocate this much memory, you'll have to be careful. If size_t (the type accepted by malloc) is a 32-bit type on your machine, but int is 16 bits, you might be able to get away with writing 300 * (300 * sizeof(double)) (see question 3.14). Otherwise, you'll have to break your data structure up into smaller chunks, or use a 32-bit machine or compiler, or use some nonstandard memory allocation functions. See also questions 7.15 and 19.23.

comp.lang.c FAQ list · Question 7.17


A: Under the segmented architecture of PC compatibles, it can be difficult to use more than 640K with any degree of transparency, especially under MS-DOS. See also question 19.23.

comp.lang.c FAQ list · Question 7.18


A: One improvement, which is particularly attractive if all nodes are the same size, is to place unused nodes on your own free list, rather than actually freeing them. (This approach works well when one kind of data structure dominates a program's memory use, but it can cause as many problems as it solves if so much memory is tied up in the list of unused nodes that it isn't available for other purposes.)

comp.lang.c FAQ list · Question 7.19


A: It is unfortunately very easy to corrupt malloc's internal data structures, and the resulting problems can be stubborn. The most common source of problems is writing more to a malloc'ed region than it was allocated to hold; a particularly common bug is to malloc(strlen(s)) instead of strlen(s) + 1. [footnote] Other problems may involve using pointers to memory that has been freed, freeing pointers twice, freeing pointers not obtained from malloc, freeing null pointers, allocating 0-sized objects (see question 11.26), or trying to realloc a null pointer (see question 7.30). (The last three--freeing null pointers, allocating 0-sized objects, and reallocing a null pointer--are sanctioned by the Standard, though older implementations often have problems.) Consequences of any of these errors can show up long after the actual mistake and in unrelated sections of code, making diagnosis of the problem quite difficult.

Most implementations of malloc are particularly vulnerable to these problems because they store crucial pieces of internal information directly adjacent to the blocks of memory they return, making them easy prey for stray user pointers.

See also questions 7.15, 7.26, 16.8, and 18.2.

comp.lang.c FAQ list · Question 7.19b

Q: I'm dynamically allocating an array, like this:

malloc isn't returning NULL, but the code isn't working.

A: malloc is a low-level, typeless allocator. It doesn't know how you're going to use the memory; all it does is to allocate as many bytes of memory as you ask it. Therefore (except when you're allocating arrays of char) you must multiply by the size of the elements in the array you're allocating:

	int *iarray = malloc(nints * sizeof(int));
	int *iarray = malloc(nints * sizeof(*iarray));
(The latter fragment can be more reliable if the type of iarray might change, since there's only one place to change it. Also, the casts have been removed; see question 7.7.) Compare question 4.4, and see also question 7.8.

comp.lang.c FAQ list · Question 7.20

Q: You can't use dynamically-allocated memory after you free it, can you?

A: No. Some early documentation for malloc stated that the contents of freed memory were ``left undisturbed,'' but this ill-advised guarantee was never universal and is not required by the C Standard.

Few programmers would use the contents of freed memory deliberately, but it is easy to do so accidentally. Consider the following (correct) code for freeing a singly-linked list:

	struct list *listp, *nextp;
		nextp = listp->next;
and notice what would happen if the more-obvious loop iteration expression listp = listp->next were used, without the temporary nextp pointer.

References: K&R2 Sec. 7.8.5 p. 167
ISO Sec. 7.10.3
Rationale Sec.
H&S Sec. 16.2 p. 387
CT&P Sec. 7.10 p. 95

comp.lang.c FAQ list · Question 7.21

Q: Why isn't a pointer null after calling free?




References: ISO Sec. 7.10.3
Rationale Sec.

comp.lang.c FAQ list · Question 7.22


A: Yes. Remember that a pointer is different from what it points to. Local variables [footnote] are deallocated when the function returns, but in the case of a pointer variable, this means that the pointer is deallocated, not what it points to. Memory allocated with malloc always persists until you explicitly free it. (If the only pointer to a block of malloc'ed memory is a local pointer, and if that pointer disappears, there will be no way to free that block.) In general, for every call to malloc, there should be a corresponding call to free.

comp.lang.c FAQ list · Question 7.23


A: Yes. malloc knows nothing about structure declarations or about the contents of allocated memory; it especially does not know whether allocated memory contains pointers to other allocated memory. In general, you must arrange that each pointer returned from malloc be individually passed to free, exactly once (if it is freed at all).

A good rule of thumb is that for each call to malloc in a program, you should be able to point at the call to free which frees the memory allocated by that malloc call. (In many cases, you'll free blocks of memory in the reverse order you allocated them, although this order is by no means required.)

See also question 7.24.

comp.lang.c FAQ list · Question 7.24

Q: Must I free allocated memory before the program exits?

A: You shouldn't have to. A real operating system definitively reclaims all memory and other resources when a program exits; the system cannot afford to have memory integrity depend on the whims of random programs. (Strictly speaking, it is not even free's job to return memory to the operating system; see question 7.25.) Nevertheless, some personal computers are said not to reliably recover memory unless it was freed before exiting, and all that can be inferred from the ANSI/ISO C Standard is that this is a ``quality of implementation issue.''

On the other hand, the C library free function rarely returns memory back to the operating system (see question 7.25), so calling free probably isn't the way to guarantee that an exiting program's memory is recovered by the system, anyway.

In any case, it can be considered good practice to explicitly free all memory--for example, in case the program is ever rewritten to perform its main task more than once (perhaps under a Graphical User Interface). [footnote] On the other hand, there are programs (such as interpreters) that don't know what memory they're done with (i.e. what memory could be freed) until it's time to exit, and since all memory should be released at exit, it would be a needless, potentially expensive, and error-prone exercise for the program to explicitly free all of it.

Additional links: further explanation

References: ISO Sec.

comp.lang.c FAQ list · Question 7.25



Additional links: further reading

comp.lang.c FAQ list · Question 7.26

Q: How does free know how many bytes to free?


comp.lang.c FAQ list · Question 7.27



comp.lang.c FAQ list · Question 7.28

Q: Why doesn't sizeof tell me the size of the block of memory pointed to by a pointer?

A: sizeof tells you the size of the pointer. There is no portable way to find out the size of a malloc'ed block. (Remember, too, that sizeof operates at compile time, and see also question 7.27.)

comp.lang.c FAQ list · Question 7.29





	#include <stdio.h>
	#include <stdlib.h>

	if(newarray != NULL)
		dynarray = newarray;
	else {
		/* dynarray remains allocated */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *p, *p2, *newp;
int tmpoffset;

p = malloc(10);

tmpoffset = p2 - p;
newp = realloc(p, 20);
if(newp != NULL) {
	p = newp;		/* p may have moved */
	strcpy(p2, ", world!");

printf("%s\n", p);

See also questions 7.7 and 7.30.

References: K&R2 Sec. B5 p. 252
ISO Sec.
H&S Sec. 16.3 pp. 387-8

comp.lang.c FAQ list · Question 7.30


A: ANSI C sanctions this usage (and the related realloc(..., 0), which frees), although several earlier implementations do not support it, so it may not be fully portable. Passing an initially-null pointer to realloc can make it easier to write a self-starting incremental allocation algorithm.

Here is an example--this function reads an arbitrarily-long line into dynamically-allocated memory, reallocating the input buffer as necessary. (The caller must free the returned pointer when it is no longer needed.)

#include <stdio.h>
#include <stdlib.h>

/* read a line from fp into malloc'ed memory */
/* returns NULL on EOF or error */
/* (use feof or ferror to distinguish) */

char *agetline(FILE *fp)
	char *retbuf = NULL;
	size_t nchmax = 0;
	register int c;
	size_t nchread = 0;
	char *newbuf;

		if(nchread >= nchmax) {
			nchmax += 20;
			if(nchread >= nchmax) {	/* in case nchmax overflowed */
				return NULL;
			newbuf = realloc(retbuf, nchmax + 1);
			if(retbuf == NULL)	/* in case pre-ANSI realloc */
				newbuf = malloc(nchmax + 1);
			else	newbuf = realloc(retbuf, nchmax + 1);
						/* +1 for \0 */
			if(newbuf == NULL) {
				return NULL;

			retbuf = newbuf;

		if(c == '\n')

		retbuf[nchread++] = c;

	if(retbuf != NULL) {
		retbuf[nchread] = '\0';

		newbuf = realloc(retbuf, nchread + 1);
		if(newbuf != NULL)
			retbuf = newbuf;

	return retbuf;
(In production code, a line like nchmax += 20 can prove troublesome, as the function may do lots of reallocating. Many programmers favor multiplicative reallocation, e.g. nchmax *= 2, although it obviously isn't quite as self-starting, and can run into problems if it has to allocate a huge array but memory is limited.)

References: ISO Sec.
H&S Sec. 16.3 p. 388

comp.lang.c FAQ list · Question 7.31


A: calloc(m, n) is essentially equivalent to

p = malloc(m * n);
memset(p, 0, m * n);

There is no important difference between the two other than the number of arguments and the zero fill.[footnote]

Use whichever function is convenient. Don't rely on calloc's zero fill too much (see below); usually, it's best to initialize data structures yourself, on a field-by-field basis, especially if there are pointer fields.

calloc's zero fill is all-bits-zero, and is therefore guaranteed to yield the value 0 for all integral types (including '\0' for character types). But it does not guarantee useful null pointer values (see section 5 of this list) or floating-point zero values.

free is properly used to free the memory allocated by calloc; there is no Standard cfree function.

One imagined distinction that is not significant between malloc and calloc is whether a single element or an array of elements is being allocated. Though calloc's two-argument calling convention suggests that it is supposed to be used to allocate an array of m items of size n, there is no such requirement; it is perfectly permissible to allocate one item with calloc (by passing one argument as 1) or to allocate an array with malloc (by doing the multiplication yourself; see for example the code fragment in question 6.14). (Nor does structure padding enter into the question; any padding necessary to make arrays of structures work correctly is always handled by the compiler, and reflected by sizeof. See question 2.13.)

References: ISO Sec. 7.10.3 to
H&S Sec. 16.1 p. 386, Sec. 16.2 p. 386
PCS Sec. 11 pp. 141,142

comp.lang.c FAQ list · Question 7.32

Q: What is alloca and why is its use discouraged?

A: alloca allocates memory which is automatically freed when the function which called alloca returns. That is, memory allocated with alloca is local to a particular function's ``stack frame'' or context.

alloca cannot be written portably, [footnote] and is difficult to implement on machines without a conventional stack. Its use is problematical (and the obvious implementation on a stack-based machine fails) when its return value is passed directly to another function, as in fgets(alloca(100), 100, stdin). [footnote]

For these reasons, alloca is not Standard and cannot be used in programs which must be widely portable, no matter how useful it might be. Now that C99 supports variable-length arrays (VLA's), they can be used to more cleanly accomplish most of the tasks which alloca used to be put to.

See also question 7.22.

Additional links: an article by Gordon L. Burditt describing difficulties in implementing and using alloca

References: Rationale Sec. 4.10.3

Read sequentially: prev next up

about this FAQ list   about eskimo   search   feedback   copyright

Hosted by Eskimo North