Step 1 of 5 · Reading · ~4 min
Learn
Memory and Structs
malloc and free
Every array so far had its size written into the source. By the end of this lesson you can reserve memory whose size you only learn while the program runs, use it like an array, and hand it back correctly.
Asking the heap for bytes
malloc (from <stdlib.h>) reserves a block on the heap, memory that stays yours until you release it, and returns a pointer to its first byte. Its one argument is a byte count, not an element count:
int days;
scanf("%d", &days); /* say 4 */
double *rain = malloc(days * sizeof *rain); /* 4 * 8 = 32 bytes */
if (rain == NULL) { /* malloc can fail */
fprintf(stderr, "no memory for %d days\n", days);
return 1;
}
for (int d = 0; d < days; d++) scanf("%lf", &rain[d]);
printf("day 1: %.1f mm\n", rain[0]);
free(rain); /* the 32 bytes go back */
rain = NULL;
fprintf(stderr, ...) is printf aimed at stderr, the separate stream for error messages, so a failure report never mixes into the normal output; the File I/O lesson covers streams properly.
sizeof *rain is the size of one element (8 for a double), so the product is exactly days elements' worth. After that, rain[d] works like array indexing, because (from the Pointers lesson) indexing is "start address plus d elements". A pointer to enough bytes is a dynamic array.
The byte count is the trap. The same request for 10 ints, three ways:
| Call | Bytes | Room for |
|---|---|---|
malloc(10) | 10 | 2 ints and a half |
malloc(10 * sizeof(int)) | 40 | 10 ints |
malloc(10 * sizeof *p) | 40 | 10 ints, and stays right if p's type changes |
malloc(10) compiles without a warning. Storing 10 ints in it overflows into the allocator's own bookkeeping: the buffer overflow from the Arrays lesson, moved to the heap. With a few values it often seems to work; with thousands, the program typically dies later inside free or printf, far from the guilty line.
The bytes malloc returns are uninitialized, so the garbage rule applies. calloc(count, size) takes the count and size separately and zero-fills: calloc(days, sizeof *rain) gives four 0.0 values. When memory runs out both return NULL, and following NULL crashes, so check before first use.
The contract
Nothing frees heap memory for you. Three duties, each with a named failure:
- Free what you allocate, exactly once. Forget and you have a memory leak: invisible in a short exercise, fatal in a server that allocates in a loop.
- Never touch it after
free. The pointer still holds the old address, but the allocator immediately writes its own bookkeeping into the first bytes. Readingrain[0]afterfree(rain)is a use-after-free and can print0.0or nonsense. - Never free twice. A double free corrupts the allocator and usually aborts.
free(NULL)does nothing, which is whyrain = NULL;afterfreeis a cheap safety net.
Walking a block backwards
Storing values lets you visit them in any order. Counting down needs the same boundary care as counting up:
int left[3] = {5, 8, 13};
for (int k = 2; k >= 0; k--) { /* 2, 1, 0 */
if (k != 2) printf(", "); /* separator before all but the first printed */
printf("%d", left[k]);
}
printf("\n"); /* 13, 8, 5 */
Write k > 0 and index 0 is never visited: 13, 8. Start at k = 3 and the first read is past the end.
Common mistakes
malloc(n)instead of n elements' worth of bytes. Small inputs survive by luck; a hidden test with 2,000 values crashes or prints corrupted numbers.- Stopping the countdown at
> 0. The first value read is never printed: input1 2 3gives3 2, and a single value gives an empty line. - Summing into an
int. Three values near two billion total 5500000000, which anintcannot hold, so the sum prints negative. Uselong longand%lld. - Freeing too early.
freebefore the printing is a use-after-free; the first values come out as 0 or garbage.
Your exercise
Replace the starter's NULL with a correctly sized malloc, make the failure branch return 1, print the stored values last-to-first and then their total, and free the block. The starter already reads n and fills the block; the most likely mistake is a byte count that is too small.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…