您的位置:首页 > 其它

char* 和char[] 内存分配的区别

2012-11-29 21:37 337 查看
char * s1 = "abcd";
s1[0] = 'm';//segment fault


上面代码在gcc下编译运行将报段错误。

然而,

char s1[] = "abcd";
s1[0] = 'm';


这段代码则能够正确运行。其中包含的原理是char* 和 char[],在内存分配上的机制差异。

对于char * s = "abcd";来说, 编译器会将字符串字面量当作常量数据处理,存放在.rodata段,这样以来,s将指向.rodata段中的某处内存,

因此对该段内存的修改会引起段错误。(另,printf等格式化字符串函数中的format string 如"%d"等也会被放在.rodata中。)

对于char s1[] = "abcd";来说,"abcd"是在栈上分配内存,使用mov指令直接将值写入栈上对应内存。

使用下面代码来验证上面的描述:

#include <stdio.h>

int main()
{
char * s1 = "abcd";
char s2[] = "efghef";
}


查看汇编指令:

cString.o:     file format elf32-i386

Contents of section .text:
0000 5589e583 e4f083ec 1065a114 00000089  U........e......
0010 44240c31 c0c70424 00000000 c7442405  D$.1...$.....D$.
0020 65666768 66c74424 096566c6 44240b00  efghf.D$.ef.D$..
0030 8b54240c 65331514 00000074 05e8fcff  .T$.e3.....t....
0040 ffffc9c3                             ....
Contents of section .rodata:
0000 61626364 00                          abcd.
Contents of section .comment:
0000 00474343 3a202855 62756e74 752f4c69  .GCC: (Ubuntu/Li
0010 6e61726f 20342e35 2e322d38 7562756e  naro 4.5.2-8ubun
0020 74753429 20342e35 2e3200             tu4) 4.5.2.

Disassembly of section .text:

00000000 <main>:
0:	55                   	push   %ebp
1:	89 e5                	mov    %esp,%ebp
3:	83 e4 f0             	and    $0xfffffff0,%esp
6:	83 ec 10             	sub    $0x10,%esp
9:	65 a1 14 00 00 00    	mov    %gs:0x14,%eax
f:	89 44 24 0c          	mov    %eax,0xc(%esp)
13:	31 c0                	xor    %eax,%eax
15:	c7 04 24 00 00 00 00 	movl   $0x0,(%esp)
1c:	c7 44 24 05 65 66 67 	movl   $0x68676665,0x5(%esp)
23:	68
24:	66 c7 44 24 09 65 66 	movw   $0x6665,0x9(%esp)
2b:	c6 44 24 0b 00       	movb   $0x0,0xb(%esp)
30:	8b 54 24 0c          	mov    0xc(%esp),%edx
34:	65 33 15 14 00 00 00 	xor    %gs:0x14,%edx
3b:	74 05                	je     42 <main+0x42>
3d:	e8 fc ff ff ff       	call   3e <main+0x3e>
42:	c9                   	leave
43:	c3                   	ret
前面用蓝色标出部分为char*声明的字符串。后面蓝色标出部分位char[]字符串数组。

此外,对于函数如strcpy(s3,"abcd"),这样的调用,参数传入字符串常量的都是存储在.rodata段中的。


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: