I observed this issue in a very large C program.
The structure declaration is:
struct kc910InputParms {
char inStream[71];
}
In the program, when there is memset
operation done on this struct variable, the printf
statement prints longer than its limit(i.e. 71 characters is the limit). Please see below the output obtained while debugging in gdb.
(gdb) s
cpyInParmsToCbl (in=0xffffb9f6, out=0x80ef320) at kc190Common.c:456
456 memset((void*)out, ' ', sizeof(kc910InputParms));
(gdb) printf "<%s>\n", out.inStream
<>
(gdb) n
458 strncpy(out->inStream+16, in->system_id,strlen(in->system_id));
(gdb) printf "<%s>\n", out.inStream
< Pending>
Please notice above: There are 7 extra characters appended as "Pending" which prints the out.inStream
upto 78 characters. This introduces flaw in the subsequent stage of the program.
Can someone please help me to understand this behavior and the correct way to use memset
(if I am doing it wrong)?
If this is happening because the variable out.inStream
has not been terminated by a null character '\0'
, then my question is: Why it didn't print in the same way before memset
?
It is due to the missing terminating nul. The reason why it worked before was due to the compiler setting the memory area to nuls, or just random luck.
You are also telling strncpy
that there is space only for as many bytes as there are characters in the string so it is not adding the terminator. This is the wrong way to do it. You should tell strncpy
how many bytes are available in the destination, not how many characters are in the source. In this case 54 (70-16). And you should explicitly set the last byte to nul for the case where the source is longer than 54 characters.
printf
and other C string functions don't know anything about array sizes or memory allocations, they go by the terminating nul. So if you don't have it, they will continue until they find one, perhaps running out of the allocated memory space and causing undefined behavior. That is why you get more than 71 characters in output.