IgorZ
IgorZ

Reputation: 1164

Wrong behavior of the char arrays after strncpy

I am not a C-dev and I can get something wrong (I am doing the changes in the old code):

There is a function called strncpySafe (it is just a wrapper on strncpy as I can see):

void    strncpySafe(char *strDest, const char *strSource, int count)
{
    strncpy(strDest, strSource, count-1);
    strDest[count-1] = '\0';
}

The step by itself, where is a copy from source A to source B with an offset:

void Foo(const char *message) {
char line[1024];
...
strncpySafe(line, &message[message_offset], count);

In the last step they are modifying a line[] that was copied (the message[] should stay the same):

line[N] = 0;

On the last step I can see from a VSCode debugger that line[N] is being changed and in the same time the message[N] also modifies.
I am using Ubuntu /g++-8, -march=x86-64, -std=c++11.
Is it something about the same pointers? Is it the wrong usage of the strncpy?
Thank you.

ps: the same code is being used inside a game client for windows and linux and I can say that on windows it is not being reproduced (windows was built on an older c-compiler, haven't checked with the same c++11 build yet).

EDIT: to make it clear, the modification of the line and a message happens in the same time when I pass a step with line[N] = 0;

Removed incorrect naming of the message_offset_2. It is a count.
Let me provide an example of the execution:

strncpySafe(line, &message[5], 10); // It copies 10 elements from 5th
line[5] = 0; // this leads that message[5] also gets 0 for it's element

There are no errors with the boundaries (offsets and counters seems alright).

I agree that this code is deprecated and the logic might be unclear (why is that done that way) and I could use std::string. For me it was interesting why does it happen.

Upvotes: 0

Views: 345

Answers (1)

Vlad from Moscow
Vlad from Moscow

Reputation: 310950

Taking into account that the array message is also changed as you wrote in your question then it is evident that you are using the function incorrectly and as a result you have undefined behavior.

For example the third parameter that you named like message_offset_2 specifies the number of characters that should be copied from a string to the the destination character array. So it should not be named like message_offset_2.

Another reason of undefined behavior can be using of overlapped arrays.

So either the third argument is specified incorrectly or there takes place overlapping of character arrays.

But in any case the function is declared and defined badly.

If it is a wrapper around the standard C function strncpy then it should be declared at least like

char * strncpySafe( char * restrict s1, const char * restrict s2, size_t n );

Or if it is declared as a C++ function then

char * strncpySafe( char * s1, const char * s2, size_t n );

If the function is designed to copy n characters then the body of the function should look like

if ( n )
{
    strncpy( s1, s2, n );
    s1[n] = '\0';
}

return s1;

So the destination array shall have at least n + 1 elements.

And (the C Standard, 7.23.2.4 The strncpy function )

If copying takes place between objects that overlap, the behavior is undefined.

Upvotes: 1

Related Questions