So I've been teaching myself C, and in the hopes of learning how to properly manage memory from the beginning and write better code, I've been running Valgrind on everything. This has helped me with memory leaks, but I can't seem to get rid of this "Conditional jump or move depends on uninitialised value(s)/Uninitialised value was created by a heap allocation" situation, although I've narrowed it down to this block of code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char* test = (char*) malloc(3);
strncpy(test, "123", 2);
printf("%s\n", test);
free(test);
return 0;
}
When I run Valgrind with ---track-origins=yes
, I get this output:
==91702== Conditional jump or move depends on uninitialised value(s)
==91702== at 0x100011507: strlen (mc_replace_strmem.c:282)
==91702== by 0x1000AA338: puts (in /usr/lib/libSystem.B.dylib)
==91702== by 0x100000EFA: main (valgrind_test.c:10)
==91702== Uninitialised value was created by a heap allocation
==91702== at 0x100010345: malloc (vg_replace_malloc.c:236)
==91702== by 0x100000EEA: main (valgrind_test.c:8)
This seems like a false positive to me, but I'm not confident enough in my own knowledge to write it off as such. Maybe I'm allocating wrong or using strncpy wrong? I'm not sure.
Thanks in advance
Yes, there are false positives with Valgrind, that's why it has suppression files for particular glibc and gcc versions, for example.
The error message "Conditional jump or move depends on uninitialized value(s)" essentially means Valgrind has determined that the result of your program depends on uninitialized memory. Sometimes you will also see the message "Use of uninitialized value of size N".
No, this is broken code.
You have a memory block with 3 uninitialized characters. Then you copy "12"
into it, and don't terminate. Beware of strncpy()
.
I quote the documentation:
The strncpy() function is similar, except that not more than n bytes of src are copied. Thus, if there is no null byte among the first n bytes of src, the result will not be null-terminated.
Since there is no termination within the first 2 characters of the source, the destination is not terminated.
Idiomatic ways to use strcpy()
and strncpy()
:
If you know that the buffer has space for the string plus the NUL terminator, you can use strcpy()
. This will probably use constants, or have checks in code (you should make sure the checks are right).
Otherwise, you can do:
strncpy(dest, src, length);
dest[length - 1] = '\0';
which has the following disadvantages:
length
bytes.There is also OpenBSD's strlcpy()
.
Any other use of strcpy()/strncpy()
is potentially suspicious, and you should look at them carefully.
Bottom line: avoid C string functions for anything moderately complex, try to use some library for dynamically allocated strings. Qmail/Postfix roll their own, GNU has obstacks.
Your string has no terminator, so valgrind is probably right when it complains. Change:
strncpy(test, "123", 2);
to:
strcpy(test, "12");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With