Author | Message | Time |
---|---|---|
FrOzeN | With the following code: [code]#include <stdio.h> #include <string.h> int main(int argc, char* argv[]) { char strTemp[11]; sGetMessage(strTemp); printf("%s\n", strTemp); system("PAUSE"); return 0; } sGetMessage(char* Message) { strcpy(Message, "Hello World!"); }[/code] Should the sGetMessage function have a data type scope? Eg, [code]int sGetMessage(char* Message) { strcpy(Message, "Hello World!"); return 0; }[/code] | May 29, 2006, 10:21 PM |
Rule | Well, ISO C "forbids a definition without a datatype or storage class." So, yes, you should definitely declare a return type for sGetMessage, even if it's void. If you're compiling with gcc, it's good to use the flags "-ansi -Wall -pedantic" to check for such things. Also, since you're using system, you should include stdlib.h. It seems strange that char strTemp[11] works to hold "Hello World!".... Doesn't it make sense that you should need a character array of size [13], to hold the characters in "Hello World!" as well as the null terminating character? I tried playing around with the size of strTemp; I don't get a segmentation fault (when copying "Hello World! into strTemp) unless strTemp is less than 3 in size. Why is this?! Edit: if I declare char strTemp[0], the program still prints "Hello World!" If I declare char strTemp[1], the program prints "Hello World!" and gives me a segmentation fault. How can this be explained? | May 29, 2006, 10:52 PM |
FrOzeN | I didn't pay much attention to the character array. I originally just typed strTemp[11] thinking it would work like: [quote]strTemp[0] ="H" strTemp[1] ="e" strTemp[2] ="l" strTemp[3] ="l" strTemp[4] ="o" strTemp[5] =" " // (Space) strTemp[6] ="W" strTemp[7] ="o" strTemp[8] ="r" strTemp[9] ="l" strTemp[10] ="d" strTemp[11] ="!"[/quote] Though, now that I think of it. Declaring [11] would make [10] the highest as it starts for zero. Wasn't really thinking about it at the time because it worked when I compiled it. (I have no idea why it works either, maybe strcpy resizes the array?) [hr]I'm using Dev-Cpp and in the IDE I just click the "Compile and Run" option on the toolbar, so I'm not exactly sure which compiler it's using (I think it's MingW/GCC). | May 30, 2006, 12:23 AM |
Rule | [quote author=FrOzeN link=topic=15087.msg153408#msg153408 date=1148948589] I didn't pay much attention to the character array. I originally just typed strTemp[11] thinking it would work like: [quote]strTemp[0] ="H" strTemp[1] ="e" strTemp[2] ="l" strTemp[3] ="l" strTemp[4] ="o" strTemp[5] =" " // (Space) strTemp[6] ="W" strTemp[7] ="o" strTemp[8] ="r" strTemp[9] ="l" strTemp[10] ="d" strTemp[11] ="!"[/quote] Though, now that I think of it. Declaring [11] would make [10] the highest as it starts for zero. Wasn't really thinking about it at the time because it worked when I compiled it. [/quote] You'd need 12 places for the characters, and 1 space for the null terminating character, '\0'. Try: printf("%d\n", sizeof("Hello World!")); [quote author=FrOzeN link=topic=15087.msg153408#msg153408 date=1148948589] (I have no idea why it works either, maybe strcpy resizes the array?) [/quote] Nope, I checked this... [quote author=FrOzeN link=topic=15087.msg153408#msg153408 date=1148948589] I'm using Dev-Cpp and in the IDE I just click the "Compile and Run" option on the toolbar, so I'm not exactly sure which compiler it's using (I think it's MingW/GCC). [/quote] In that case you can probably turn on some helpful compiling/debugging options that will provide you with warnings in certain situations. | May 30, 2006, 12:38 AM |
Kp | The compiler is placing the array on the stack in such a way that there's some slack space between the last cell you requested ([10]), and the last cell which can be overwritten without destroying something important. When you make strTemp small enough, the padding is no longer sufficient and writing into the array smashes the return address. | May 30, 2006, 2:19 AM |
Rule | [quote author=Kp link=topic=15087.msg153415#msg153415 date=1148955570] The compiler is placing the array on the stack in such a way that there's some slack space between the last cell you requested ([10]), and the last cell which can be overwritten without destroying something important. When you make strTemp small enough, the padding is no longer sufficient and writing into the array smashes the return address. [/quote] Makes sense, although why would strTemp[0] not cause a segmentation fault (and work fine), yet strTemp[a] (where 0<a<4) does (but still works properly)? I imagine the memory that had those last characters stored in it previously (e.g. in the padding space) is still being called, and that is why both work. Although it's puzzling why strTemp[0] would not cause a segmentation fault and strTemp[1] would. | May 30, 2006, 2:43 AM |
Kp | That is best answered by examining the code generated by the compiler. Run gcc -S str.c and post the results. The output of gcc -v may also be enlightening. | May 30, 2006, 3:40 AM |
Rule | Diffs of .s files at end of post. frq1.c: [code] #include <stdio.h> #include <string.h> void sGetMessage(char* Message); int main(int argc, char* argv[]) { char asdf[1]; sGetMessage(asdf); printf("%s\n", asdf); return 0; } void sGetMessage(char* Message) { strcpy(Message, "Hello World!"); } [/code] Output: [quote] Hello World! Segmentation fault [/quote] frq1.s: [code] .file "frq1.c" .section .rodata .LC0: .string "%s\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax subl %eax, %esp subl $12, %esp leal -1(%ebp), %eax pushl %eax call sGetMessage addl $16, %esp subl $8, %esp leal -1(%ebp), %eax pushl %eax pushl $.LC0 call printf addl $16, %esp movl $0, %eax leave ret .size main, .-main .section .rodata .LC1: .string "Hello World!" .text .globl sGetMessage .type sGetMessage, @function sGetMessage: pushl %ebp movl %esp, %ebp subl $8, %esp subl $8, %esp pushl $.LC1 pushl 8(%ebp) call strcpy addl $16, %esp leave ret .size sGetMessage, .-sGetMessage .section .note.GNU-stack,"",@progbits [/code] Modified frq.c so that strTemp is declared to be size 0. (char strTemp[0]) Output: [quote] Hello World! [/quote] New frq.s: [code] .file "frq.c" .section .rodata .LC0: .string "%s\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $24, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax subl %eax, %esp subl $12, %esp leal -24(%ebp), %eax pushl %eax call sGetMessage addl $16, %esp subl $8, %esp leal -24(%ebp), %eax pushl %eax pushl $.LC0 call printf addl $16, %esp movl $0, %eax leave ret .size main, .-main .section .rodata .LC1: .string "Hello World!" .text .globl sGetMessage .type sGetMessage, @function sGetMessage: pushl %ebp movl %esp, %ebp subl $8, %esp subl $8, %esp pushl $.LC1 pushl 8(%ebp) call strcpy addl $16, %esp leave ret .size sGetMessage, .-sGetMessage .section .note.GNU-stack,"",@progbits [/code] frq100.s (changed strTemp to size 100): [code] .file "frq100.c" .section .rodata .LC0: .string "%s\n" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $120, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax subl %eax, %esp subl $12, %esp leal -120(%ebp), %eax pushl %eax call sGetMessage addl $16, %esp subl $8, %esp leal -120(%ebp), %eax pushl %eax pushl $.LC0 call printf addl $16, %esp movl $0, %eax leave ret .size main, .-main .section .rodata .LC1: .string "Hello World!" .text .globl sGetMessage .type sGetMessage, @function sGetMessage: pushl %ebp movl %esp, %ebp subl $8, %esp subl $8, %esp pushl $.LC1 pushl 8(%ebp) call strcpy addl $16, %esp leave ret .size sGetMessage, .-sGetMessage .section .note.GNU-stack,"",@progbits [/code] Differences between frq.s and frq1.s [code] diff frq.s frq1.s 1c1 < .file "frq.c" --- > .file "frq1.c" 11c11 < subl $24, %esp --- > subl $8, %esp 20c20 < leal -24(%ebp), %eax --- > leal -1(%ebp), %eax 25c25 < leal -24(%ebp), %eax --- > leal -1(%ebp), %eax [/code] Differences between frq1.s and frq100.s: [code] diff frq1.s frq100.s 1c1 < .file "frq1.c" --- > .file "frq100.c" 11c11 < subl $8, %esp --- > subl $120, %esp 20c20 < leal -1(%ebp), %eax --- > leal -120(%ebp), %eax 25c25 < leal -1(%ebp), %eax --- > leal -120(%ebp), %eax [/code] It looks as though strTemp[0] has an effective size of "24" (bytes?) , while strTemp[1] has 8? Why leal -1(%ebp), %eax for strTemp[1] though, and leal -24... for strTemp[0], -120 for strTemp[100]? Note: only differences between frq1.s and frq2.s (strTemp size 2), [code] diff frq2.s frq1.s 1c1 < .file "frq2.c" --- > .file "frq1.c" 20c20 < leal -2(%ebp), %eax --- > leal -1(%ebp), %eax 25c25 < leal -2(%ebp), %eax --- > leal -1(%ebp), %eax [/code] e.g. no subl difference | May 30, 2006, 6:02 PM |