#unclear strcpy behavior

1 messages · Page 1 of 1 (latest)

celest moon
#

Hey there,
I'm currently trying to get into C.
While messing around with strcpy I had some unexpected results that I don't really understand.

So I wrote this method to switch the values of two string vars:

void switchValues(char* first, char* second)
{
    int size = sizeof(second);
    char temp[size];

    strcpy(temp, second);
    strcpy(second, first);
    strcpy(first, temp);
}

As long as first and second point to arrays of the same size everything works fine.
If one is smaller, it should not work correctly - as we should expect.

My problem is with the way it does not work correctly.

I call it like this

    char name1[] = "John";
    char name2[] = "James";
    switchValues(name1, name2);

As long as the size of name2 is greater everything still works.

Before
name1: John
name2: James

After
name1: James
name2: John

But if name1 contains the greater value I end up with some weird concatenation.

Before
name1: James
name2: John

After
name1: John
name2: JamesJohn

Does anybody know why there is a difference based on the size of the arrays - and more importantly - why it ends up in concatenation?
I mean name1 should not fit into name2, yet name2 ends up being both values together.

hasty bough
#

Don’t use sizeof to get the size of a string. Use strlen

celest moon
#

ah yeah thx
I was wondering why sizeof gets me len+1

#

so this concatenation thing is based on the fact that the array is to small to contain the data, but why does it happen and how does the whole concatenated string fit into the array that couldn't fit the other value in the first place

hasty bough
#

I am not sure how it works, maybe @oblique portal can explain

celest moon
#

It seems to be that strcpy copies the whole string to the location of name2. But only the number of chars that fit into the array are really part of the array range in memory. When calling printf, it seems to print everything starting from the first element of the array till the next null terminator. So it print more than the boundaries of name2.

This explains why the size of the array is smaller than the string len

After
name1: John
name1 sizeof: 6, len: 4
name2: JamesJohn
name2 sizeof: 5, len: 9

something like that...

oblique portal
#

When you pass an array to a function it decays to a pointer to the first element of the array.

#

So when you take sizeof, it's returning the size of the pointer, and not the size of the array.

celest moon
#

the sizeof above is from the calling function, so not the pointer

#

like this

char name1[] = "James";
sizeof(name1)
oblique portal
#

Yes, that will return the size of the array.

celest moon
oblique portal
#

Which in this case is 6.

#

Anyway, let me read the rest! haha sorry

#

strcpy(first, temp);

#

the destination is smaller than the source.

#

so you're corrupting stuff.

#

since we know strlen(temp) > strlen(first), yet you're trying to stuff it inside it

celest moon
hallow radish
#

Buffer overflow

celest moon
#

ahhh I see
It gets clearer if you choose greater values...

originally there is John\0 in name2
now I copy James\0 which ends up as James in name2 - the missing \0 is not copied
so I have now name2 and name1 next to each other in memory and since there is no \0 for name2, I get the values of both printed when it reaches the \0 of name1

so it looks something like this

Address | Value | Array
 101    |   J   |  name2
 102    |   a   |  name2
 103    |   m   |  name2
 104    |   e   |  name2
 105    |   s   |  name2
 106    |   J   |  name1
 107    |   o   |  name1
 108    |   h   |  name1
 109    |   n   |  name1
 110    |  \0   |  name1
celest moon
#

yeah seems legit
this is the actual output

name2[0]: 0061FF05 -> J
name2[1]: 0061FF06 -> a
name2[2]: 0061FF07 -> m
name2[3]: 0061FF08 -> e
name2[4]: 0061FF09 -> s
---
name1[0]: 0061FF0A -> J
name1[1]: 0061FF0B -> o
name1[2]: 0061FF0C -> h
name1[3]: 0061FF0D -> n
name1[4]: 0061FF0E ->
name1[5]: 0061FF0F ->

so if name1 would be filled too, it would even continue to read

I guess I have my explanation