char *answer; printf("Type something:\n"); gets(answer); printf("You typed \"%s\"\n", answer);
The pointer variable "answer," which is handed to the gets function as the location into which the response should be stored, has not been set to point to any valid storage. That is, we cannot say where the pointer "answer" points. (Since local variables are not initialized, and typically contain garbage, it is not even guaranteed that "answer" starts out as a null pointer. See question 17.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 <string.h> char answer[100], *p; printf("Type something:\n"); fgets(answer, sizeof(answer), stdin); if((p = strchr(answer, '\n')) != NULL) *p = '\0'; printf("You typed \"%s\"\n", answer);
Note that this example also uses fgets()
instead of gets()
(always a
good idea; see question 11.6), allowing the size of the array to
be specified, so that the end of the array will not be
overwritten if the user types an overly-long line.
(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.
strcat
to work. I triedchar *s1 = "Hello, "; char *s2 = "world!"; char *s3 = strcat(s1, s2);
Again, the problem is that space for the concatenated result is
not properly allocated. C does not provide an automatically-
managed string type. C compilers only allocate memory for
objects explicitly mentioned in the source code (in the case of
"strings," this includes character arrays and string literals).
The programmer must arrange (explicitly) for sufficient space
for the results of run-time operations such as string
concatenation, typically by declaring arrays, or by calling
malloc
. (See also question 17.20.)
strcat performs no allocation; the second string is appended to the first one, in place. Therefore, one fix would be to declare the first string as an array with sufficient space:
char s1[20] = "Hello, ";
Since strcat returns the value of its first argument (s1, in this case), the s3 variable is superfluous.
References: CT&P Sec. 3.2 p. 32.
strcat
says that it takes two char
*
's as
arguments. How am I supposed to know to allocate things?
In general, when using pointers you always have to consider memory allocation, at least to make sure that the compiler is doing it for you. If a library routine'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 can be
misleading. The code fragments presented there are closer to
the function definition used by the call's implementor than the
invocation used by the caller. In particular, many routines
which accept pointers (e.g. to structs or strings), are usually
called with the address of some object (a struct, or an array --
see questions 2.3 and 2.4.) Another common example is stat()
.
Make sure that the memory to which the function returns a
pointer is correctly allocated. The returned pointer should be
to a statically-allocated buffer, or to a buffer passed in by
the caller, or to memory obtained with malloc()
,
but not to a local (auto) array.
In other words,
never do something like
char *f() { char buf[10]; /* ... */ return buf; }One fix (which is imperfect, especially if
f()
is called
recursively, or if several of its return values are needed
simultaneously) would to to declare the buffer as
static char buf[10];See also question 17.5.
malloc
to the pointer type being allocated?
Before ANSI/ISO Standard C introduced the void
*
generic pointer
type, these casts were typically required to silence warnings
about assignment between incompatible pointer types. (Under
ANSI/ISO Standard C, these casts are not required.)
No. Some early documentation for malloc
stated that the contents of
freed memory was "left undisturbed;" this ill-advised guarantee
was never universal and is not required by ANSI.
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; for(listp = base; listp != NULL; listp = nextp) { nextp = listp->next; free((char *)listp); }
and notice what would happen if the more-obvious loop iteration
expression listp = listp->next
were used, without the temporary
nextp
pointer.
References: ANSI Rationale Sec. 4.10.3.2 p. 102; CT&P Sec. 7.10 p. 95.
free()
know how many bytes to free?
The malloc
/free
package remembers the size of each block it
allocates and returns, so it is not necessary to remind it of
the size when freeing.
malloc
package to find out how big an
allocated block is?
Not portably.
Yes. In general, you must arrange that each pointer returned
from malloc
be individually passed to free
, exactly once (if it
is freed at all).
Most implementations of malloc
/free
do not return freed memory
to the operating system (if there is one), but merely make it
available for future malloc
calls within the same process.
free
allocated memory before the program exits?References: ANSI Sec. 4.10.3.2 .
realloc()
? Why would you want to?
ANSI C sanctions this usage (and the related realloc(..., 0)
,
which frees), but several earlier implementations do not support
it, so it is not widely portable. Passing an initially-null
pointer to realloc
can make it easier to write a self-starting
incremental allocation algorithm.
References: ANSI Sec. 4.10.3.4 .
calloc
and malloc
? Is it safe to
use calloc
's zero-fill guarantee for pointer and floating-point
values? Does free
work on memory allocated with calloc
, or do
you need a cfree
?
calloc(m, n)
is essentially equivalent to
p = malloc(m * n); memset(p, 0, m * n);
The zero fill is all-bits-zero, and does not therefore guarantee
useful zero values for pointers (see section 1 of this list) or
floating-point values. free
can (and should) be used to free
the memory allocated by calloc
.
References: ANSI Secs. 4.10.3 to 4.10.3.2 .
alloca
and why is its use discouraged?
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, and is difficult to implement
on machines without a 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)
.
For these reasons, alloca
cannot be used in programs which must
be widely portable, no matter how useful it might be.
References: ANSI Rationale Sec. 4.10.3 p. 102.