Invalid Access
Out-of-bounds and uninitialized.
Invalid Access is a free C Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Beyond Leaks
Leaks waste memory, but invalid access bugs corrupt it. memcheck catches several kinds:
- Reading or writing past the end of a buffer
- Using memory after
free - Reading uninitialized values
- Reading or writing through a bad pointer
These cause the most dangerous, hardest-to-reproduce crashes.
Out-of-Bounds Write
This allocates room for 5 ints but writes to index 5, the sixth slot.
Index 5 is one element past the end. memcheck reports an Invalid write of size 4 at this line.
#include <stdlib.h>
int main(void) {
int *a = malloc(5 * sizeof(int));
a[5] = 99; /* valid indices are 0..4 */
free(a);
return 0;
}Reading The Error
The report names the operation, the size, and the relationship to the block:
Invalid write of size 4Address 0x... is 0 bytes after a block of size 20 alloc'd
'0 bytes after a block of size 20' tells you the access landed immediately past a 20-byte (5-int) allocation.
Out-of-Bounds Read
Reads are caught too. Here the loop runs one element too far.
memcheck flags an Invalid read of size 4 on the final iteration, even though the program might 'work' by luck.
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *a = calloc(3, sizeof(int));
for (int i = 0; i <= 3; i++) /* should be i < 3 */
printf("%d\n", a[i]);
free(a);
return 0;
}Uninitialized Values
malloc does not zero memory. Using it before assigning produces an unpredictable value.
memcheck reports Conditional jump or move depends on uninitialised value(s) when such a value affects control flow or output.
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *p = malloc(sizeof(int));
if (*p == 0) /* *p was never set */
printf("zero\n");
free(p);
return 0;
}Why Uninitialized Reports Lag
memcheck does not complain the instant you read uninitialized memory. It tracks 'definedness' and only reports when an undefined value actually matters, such as a branch, output, or system call.
This avoids false alarms when you copy uninitialized bytes around harmlessly.
Use After Free
Touching memory after freeing it is undefined behavior. memcheck detects it precisely.
It reports Invalid read of size 4 with the note Address ... is 0 bytes inside a block of size 4 free'd, and even shows where the free happened.
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *p = malloc(sizeof(int));
*p = 7;
free(p);
printf("%d\n", *p); /* read after free */
return 0;
}Double Free
Freeing the same pointer twice corrupts the allocator's bookkeeping.
memcheck reports Invalid free() and shows both the current free and the original allocation, making the mistake obvious.
#include <stdlib.h>
int main(void) {
int *p = malloc(sizeof(int));
free(p);
free(p); /* freed twice */
return 0;
}Track Origins
For uninitialized-value errors, add --track-origins=yes.
memcheck then reports where the bad value was created, not just where it was used, turning a vague warning into a precise fix.
valgrind --track-origins=yes ./progStack and Globals
memcheck excels at heap errors. For overflows on the stack or in global arrays, its coverage is weaker.
There, AddressSanitizer (gcc -fsanitize=address) is often the better choice. The two tools complement each other.
Off-By-One: The Null Terminator
A frequent heap overflow is forgetting the string terminator. strlen returns 5 for 'hello', but the string needs 6 bytes to store the trailing '\0'.
memcheck reports an Invalid write when strcpy writes that final byte past the end.
#include <stdlib.h>
#include <string.h>
int main(void) {
char *s = malloc(strlen("hello")); /* needs +1 */
strcpy(s, "hello"); /* writes the '\0' past end */
free(s);
return 0;
}Quick Check
Identify what memcheck reports for the snippet.
Recap
You can now spot invalid-access bugs:
- Out-of-bounds reads/writes show as Invalid read/write with the block offset
- Uninitialized values are flagged when they affect a decision or output
- Use-after-free and double-free are detected with both call sites
--track-origins=yespinpoints undefined values; pair with ASan for stack bugs
Next: reading the full report.
Frequently asked questions
Is the “Invalid Access” lesson free?
Yes — the full text of “Invalid Access” is free to read here on the web, and the C Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C Academy course, upgrade to CoddyKit PRO.
What will I learn in “Invalid Access”?
Out-of-bounds and uninitialized. You practise C Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start C Academy?
No prior experience is required. C Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Invalid Access” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this C Academy lesson?
Yes. Every C Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Why Valgrind
- Detecting Leaks
- Invalid Access
- Reading Reports