strcpy and string presentation in memory
-
26-12-2019 - |
Question
I have a program like this(x86_64 GNU/Linux)
int main()
{
char s[] = "123456789";
char d[] = "123";
strcpy(d, s);
printf("%p, %0p\n", s, d);
printf("%s, %s", s, d);
return 0;
}
and the output is : 0xeb6d2930 0xeb6d2910 123456789 123456789 I am little confused with the result I think the program in the memory is like this:
- '9','\0' . .
- '5','6','7','8'
- 0x7fff813af310: '1','2','3','4'
- 0x7fff813af300: '1','2','3','\0'
so the result should be *s = "789", *d = "123456789"
could you guys explain why the result isn't as I thought? I changed the format specifier to %p to print the address of d and s I know that s and d are overlapped so there is not enough space for d to hold s which may lead to undefined behaviour,but anyway I was wondering why the result is *s = "123456789" *d = "123456789"
Solution
From the output you show the address layout and it's initial content seem to be:
offset 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
d: 0xeb6d2910 30 31 32 00 xx xx xx xx xx xx xx xx xx xx xx xx | 1 2 3 . . . . . . . . . . . . .
0xeb6d2920 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx | . . . . . . . . . . . . . . . .
s: 0xeb6d2930 30 31 32 33 34 35 36 37 38 39 00 xx xx xx xx xx | 1 2 3 4 5 6 7 8 9 . . . . . . .
After the strcpy(d, s)
:
offset 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
d: 0xeb6d2910 30 31 32 33 34 35 36 37 38 39 00 xx xx xx xx xx | 1 2 3 4 5 6 7 8 9 . . . . . . .
0xeb6d2920 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx | . . . . . . . . . . . . . . . .
s: 0xeb6d2930 30 31 32 33 34 35 36 37 38 39 00 xx xx xx xx xx | 1 2 3 4 5 6 7 8 9 . . . . . . .
However, as for d
fewer memory had been allocated as used during strcpy()
the code invokes undefeind behaviour.
OTHER TIPS
Your program has undefined behavior on these two counts:
- Buffer overflow with
strcpy()
: Do not write to memory you do not own. - Wrong format specifier for
printf()
: Use%p
to print pointer addresses. Only works for data-pointers though.
Please use the proper prototype for main
, you nearly have it (this might be UB, though I did not follow all the argument):
int main(void)
int main(int argc, char* argv[])
or compatible or implementation defined extensions are valid.
Undefined Behavior means everything goes, even nasal demons.
Your program invokes undefined behavior because:
1. d
doesn't have enough space to hold the string larger than 4
bytes (including \0
).
2. You are using wrong format specifier to print the address.
Result is either expected or unexpected.