Like the title say I really need help of understanding, why this code is treated on my system ( linux mint 19
, GCC-8.0.1
, valgrind-3.13.0
, c17
) as NOT valid code:
#include <stdio.h>
#include <string.h>
void printThis( const char *const ptr );
int main( void) {
char a[10] = "asds";
char b[10] = "1234567890";
strcpy ( a, b );
printThis( a );
}
void printThis( const char *const ptr ){
printf("Copy completed! : %s\n", ptr );
}
Valgrind reports the problem here:
==6973== Memcheck, a memory error detector ==6973== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==6973== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==6973== Command: /home/michi/Templates/Cprogram/bin/Debug/Cprogram ==6973== ==6973== Source and destination overlap in strcpy(0x1ffefffd14, 0x1ffefffd1e) ==6973== at 0x4C32E97: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==6973== by 0x108724: main (main.c:12) ==6973== Copy completed! : 1234567890 ==6973== ==6973== HEAP SUMMARY: ==6973== in use at exit: 0 bytes in 0 blocks ==6973== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated ==6973== ==6973== All heap blocks were freed -- no leaks are possible ==6973== ==6973== For counts of detected and suppressed errors, rerun with: -v ==6973== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
and this one as Valid code:
#include <stdio.h>
void strcpy2(char *s, char *t);
void printThis( const char *const ptr );
int main( void) {
char a[10] = "asds";
char b[10] = "1234567890";
strcpy2( a, b );
printThis( a );
}
void strcpy2(char *s, char *t) {
while ( ( *(s++) = *(t++) ) );
}
void printThis( const char *const ptr ){
printf("Copy completed! : %s\n", ptr );
}
Valgrind output:
==7025== Memcheck, a memory error detector ==7025== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==7025== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==7025== Command: /home/michi/Templates/Cprogram/bin/Debug/Cprogram ==7025== Copy completed! : 1234567890 ==7025== ==7025== HEAP SUMMARY: ==7025== in use at exit: 0 bytes in 0 blocks ==7025== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated ==7025== ==7025== All heap blocks were freed -- no leaks are possible ==7025== ==7025== For counts of detected and suppressed errors, rerun with: -v ==7025== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Compiled with O0
, O1
, O2
and O3
and GCC flags:
-Wpedantic -std=c17 -Wall -Wextra -Werror -Wstrict-prototypes -Wmissing-prototypes -Wmisleading-indentation -Wduplicated-cond -Wold-style-definition -Wconversion -Wshadow -Winit-self -Wfloat-equal -Wwrite-strings -O0 -g
Valgrind can catch only certain kinds of errors. It cannot instrument the stack, hence it would not see the error with your
strcpy2
. OTOH thestrcpy
is replaced by a version that does check if the source and destination overlap - it could catch this only becausea + 10 == b
in your compiled program!To catch this kind of error use GCC's
-fsanitize=address
: