42 Common Core — Libft: Rebuilding the C Standard Library
Part of the project CodeTester — An Interactive C Tester for 42 Projects
Part 1 of 3 in 42 Common Core
- 42 Common Core — Libft: Rebuilding the C Standard Library
- 42 Common Core — ft_printf: Variadic Functions and Format Parsing
- 42 Common Core — get_next_line: Reading a File One Line at a Time
Libft is the first project of the 42 Common Core: write your own C library, libft.a, that
re-implements a selection of libc functions plus a set of utilities the standard library
doesn’t provide. Almost every later project forbids most of libc, so this library becomes the
foundation for everything that follows.
The rules are strict: only malloc, free and write from the outside world, everything
compiled with -Wall -Wextra -Werror, and the code must follow the 42 Norm (at most 25
lines per function, 5 functions per file, declarations at the top…).
What’s in the library
| Part | Contents |
|---|---|
| Libc functions | ctype checks, memset / memcpy / memmove, strlen, strlcpy / strlcat, strnstr, atoi, calloc, strdup… |
| Additional functions | substr, strjoin, strtrim, split, itoa, strmapi, striteri, the put*_fd family |
| Linked lists | lstnew, lstadd_front/back, lstsize, lstlast, lstdelone, lstclear, lstiter, lstmap |
All prototypes live in a single libft.h, and the Makefile packs the objects into a static
archive with ar rcs, so any later project only needs #include "libft.h" and libft.a.
Overlapping memory: memcpy vs memmove
memcpy is allowed to assume the two areas don’t overlap; memmove isn’t. If the destination
starts inside the source and you copy forwards, you overwrite bytes before you’ve read them.
The fix is to pick the copy direction from the pointer order:
if (d < s)
while (n--)
*d++ = *s++; /* destination before source: copy forwards */
else
while (n--)
d[n] = s[n]; /* destination after source: copy backwards */
Size-bounded strings: strlcpy and strlcat
These BSD functions are easy to get almost right. The details that count:
- they always NUL-terminate when
size > 0; - they return the length of the string they tried to create (
strlen(src), ordst_len + src_len), so the caller can detect truncation withret >= size; strlcatmust not read pastsizebytes ofdstwhen it isn’t terminated within them.
The return value is what most tests catch: returning the number of bytes actually copied looks fine on short strings and fails as soon as truncation happens.
Clean failure in allocating functions
Every function that returns a pointer can fail. ft_split is the classic trap: it makes one
allocation for the array, then one per word. If the fourth word fails, the first three must be
freed, or they leak.
strs[index] = (char *)malloc(str - from_ptr + 1);
if (!strs[index])
return (free_all(strs, index)); /* frees words 0..index-1, then the array */
The same rule applies to ft_lstmap: if creating a node fails, the partly built list must be
cleared with del, and the content f just returned must be freed too, before returning NULL.
Edge cases worth knowing
ft_itoa(INT_MIN):-INT_MINoverflows anint, so the conversion has to work on a wider or unsigned type.ft_calloc(nmemb, size):nmemb * sizecan overflowsize_t; a correct implementation checks for it before allocating.ft_substrwithstartbeyond the string must return an empty string, notNULL.- The
ctypefunctions take anintthat may beEOFor a value above 127.
How CodeTester checks it
Writing a good tester taught me more about these functions than writing them. For libft, CodeTester runs:
- one suite per function (all 43), each in a forked process, so a crash in one doesn’t hide
the others; missing functions are reported as
MISSINGthanks to weak symbols; - comparisons against the real
libcfunction wherever one exists; - a memory suite that wraps
mallocand makes the 1st, 2nd, 3rd… allocation fail in turn, checking thatft_split,ft_strjoin,ft_strtrim,ft_itoaand the other allocating functions returnNULLand free everything they had already allocated; - subject checks: Makefile rules, no relinking, flags, library and header names, forbidden functions.
Result: 100/100, including the linked-list functions.