1
yuelang85 2012-12-05 12:56:57 +08:00
??楼主想说啥?
|
2
gracehunter OP @yuelang85 刚才不小心点了发布,现在改好了
|
3
vampirekiss 2012-12-05 13:10:23 +08:00
返回了一个指向临时变量的指针,当函数执行完时,A会被销毁,指针指向的内容是未知的。
|
4
laskuma 2012-12-05 13:44:58 +08:00
local variable的scope只到本function结尾。之后就失效。如果stack再次增长的话会被覆盖成奇怪的东西。
改成 char* funA() { char *b = "Hello, world."; char *a = (char *)malloc(sizeof(char) * strlen(b)); strcpy(a, b); return a; } |
5
ShadowStar 2012-12-05 14:11:57 +08:00
局部变量存储于栈空间,函数调用返回后就会失效,被其他函数复用相同栈空间。
但是!对于@gracehunter 以及@laskuma 的代码来说,是可以的。 因为对于""中的字符串会被编码在.rodata段,是静态存储的,返回的是这个字符串的地址。 |
7
laskuma 2012-12-05 21:42:57 +08:00
@ShadowStar LZ的方法不行
|
8
raptium 2012-12-05 22:23:19 +08:00
@ShadowStar 本來我以為你這麼說是對的
但是看了一下 gcc -S 編譯出來的 asm 似乎不是這樣 "hello world" 不是在 .rodata 段的,而是直接四句 mov 寫到 stack 上的(一句 mov 可以過去 4 個字符),所以返回是會出問題的 於是我想可能是字符串太短了,嘗試把 hello world 改成一個很長很長的字符串,這樣編譯出來字符串的確保存在 .rodata 段了。但是,再看一下後面代碼很長,基本就是好不容易算出來了兩個指針地址,然後用 rep movsd 把 .rodata 裏的數據複製到了 A 的位置,所以還是在 stack 上。 綜上,樓主怎麼寫是不行的。 |
9
magicsilence 2012-12-06 01:07:46 +08:00
@raptium 是在.rodata段中, gcc 4.6
----- [lithium@ubuntu:~/code/gcc/test] > cat t.c #include <stdio.h> char* t() { char* p = "this is a test prog"; return p; } int main(int argc, char *argv[]) { char* p = t(); printf("Addr p: %x\n", p); return 0; } [lithium@ubuntu:~/code/gcc/test] > ./a.out Addr p: 40063c [lithium@ubuntu:~/code/gcc/test] > objdump -hs a.out | grep ".rodata" -3 CONTENTS, ALLOC, LOAD, READONLY, CODE 13 .fini 0000000e 0000000000400628 0000000000400628 00000628 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 14 .rodata 00000024 0000000000400638 0000000000400638 00000638 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 15 .eh_frame_hdr 00000034 000000000040065c 000000000040065c 0000065c 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA -- 400620 83c4085b 5dc39090 ...[]... Contents of section .fini: 400628 4883ec08 e82ffeff ff4883c4 08c3 H..../...H.... Contents of section .rodata: 400638 01000200 74686973 20697320 61207465 ....this is a te 400648 73742070 726f6700 41646472 20703a20 st prog.Addr p: 400658 25780a00 %x.. |
11
timonwong 2012-12-06 02:51:17 +08:00
@magicsilence
字符数组应该是不保证一定在.rodata上的,尤其A还定义的还是个可写的数组。 你的代码展示的是 指向string literal的字符串指针,由于GCC默认就开了string pooling,应该是直接放到.rodata段中的,其它不默认开string pooling的编译器(比如MSVC),结果就很难说了。 |
12
raptium 2012-12-06 11:05:57 +08:00
@magicsilence 是在 rodata 上有 但是返回的时候会先整段复制到栈里 然后返回栈地址
|
13
clowwindy 2012-12-06 11:11:15 +08:00
养成好习惯,const char *
|
14
raptium 2012-12-06 11:18:11 +08:00
@magicsilence 不對,剛在車上沒細看
你的程序和樓主的不一樣 char *p = "...." 和 char p[] = "...." 不是一個意思 你這個直接返回指向 .rodata 的地址就行了 chap p[] 會在棧上分配空間的 |
16
ShadowStar 2012-12-06 12:28:37 +08:00
@raptium 抱歉,我确实有点想当然了。
因为Mac自带的toolchain没有objdump等工具,所以我只能用mips64的toolchain验证一下。 /tmp % cat c.c #include <stdio.h> #include <stdlib.h> char* funA(){ char A[] = "Hello, world."; return A; } int main ( int argc, char *argv[] ) { printf("%s\n", funA()); return EXIT_SUCCESS; } /* ---- end of function main ---- */ /tmp % mips64-octeon-linux-gnu-gcc -O2 -o c c.c c.c: In function 'funA': c.c:6: warning: function returns address of local variable /tmp % mips64-octeon-linux-gnu-objdump -s c | sed -n '/\.rodata/,/Contents/p' Contents of section .rodata: 120000b40 00020001 00000000 48656c6c 6f2c2077 ........Hello, w 120000b50 6f726c64 2e000000 orld.... Contents of section .interp: /tmp % |
17
magicsilence 2012-12-06 13:50:51 +08:00
|
18
timonwong 2012-12-06 14:51:26 +08:00
|