C/C++程序(常量字符串)内存分布

C/C++程序一般分为
1.程序段(text):程序段为程序代码在内存中的映射.一个程序可以在内存中多有个副本,通常为只读.
2.初始化的全局变量(data):在程序运行值初已经对变量进行初始化的
3.未初始化的全局变量(bss):在程序运行初未对变量进行初始化的数据,特点是:可读写的,在程序执行之前BSS段会自动清0。所以,未初始的全局变量在程序执行之前已经成0了。
4.堆(stack):存储局部,临时变量,在程序块开始时自动分配内存,结束时自动释放内存.存储函数的返回指针.
5.栈(heap):存储动态内存分配,需要程序员手工分配,手工释放.
C/C++程序(常量字符串)内存分布
网上搜到的、书中所讲的一般都如图所示,我比较疑惑的是char *p = "Hello"这种字符串常量所在区域,有一种说法是还有一段文字常量区 ,常量字符串就是放在这里的。这段常量区在哪里,原以为应该在text区域或之后,因为都是只读的区域,结果却很意外。
测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>


int gloUninit1;
int gloUninit2;
int gloInit1 = 1;
int gloInit2 = 1;



char * pStr1 = "Hello";
char * pStr2 = "World";

char * pStr3 = "Hello";
char * pStr4 = "more";
const int con = 1;
char str[] = "Hello";

int Fun1(int a)
{
    return a;
}
int Fun2(int a)
{
    return a;
}
int main()
{

    int (*pFun1)(int a);
    int (*pFun2)(int a);
    pFun1 = Fun1;
    pFun2 = Fun2;
    char * pStr5 = "this";
    printf("gloUninit1 address: %d\n\
gloUninit2 address: %d\n\
gloInit1 address: %d\n\
gloInit2 address: %d\n\
const address: %d\n\
pStr1(hello): %d\n\
pStr2(world): %d\n\
pStr3(hello): %d\n\
Str(hello): %d\n\
Fun1 address: %d\n\
Fun2 address: %d\n\
pStr1(hello) address: %d\n\
pStr2(world) address: %d\n\
pStr3(hello) address: %d\n\
Str(hello) address: %d\n",&gloUninit1,&gloUninit2,&gloInit1,&gloInit2,&con,pStr1,pStr2,pStr3,str,pFun1,pFun2,&pStr1,&pStr2,&pStr3,&str);



    printf("(this)%d\n","this");
    printf("(more)%d\n","more");
    printf("(did)%d\n","did");


    return 0;
}

 

 

程序输出结果:C/C++程序(常量字符串)内存分布

可以看出在内存低位的是函数地址,也就是text段。

紧接着text段的就是data段,可以看到初始化的全局变量按顺序排列开来,从gloInit1一直到Str,因为都是四字节的变量,可以看到内存地址也是按照4字节递增。

在往上就是常量区域了,常量con以及Hello,World,more,this这四个字符串的地址,可以看出编译器将相同的字符串优化到一处,所以pStr1和pStr3,pStr4和“more”的地址都是一样的,pStr1和pStr2相差6字节正好是“Hello”字符串长度,亦可以看出在分配int型常量con时进行了内存对齐。这里比较奇怪的是“did”字符串,依然在bss段之下,却和前几个字符串间隔了一段距离,和“this”的差别在于this之前有赋值给pStr5,有谁知道原因还望提点一二。

在往上就是bss段了。未初始化的全局变量存放在这里。

堆内存动态申请分配,栈由操作系统控制,分布如图示

 

转载于:https://www.cnblogs.com/ssmouse/archive/2013/01/21/2870614.html