侯捷 - C++ Startup 揭密:C++ 程序的生前和死后 (一)

前言:如何自定Startup code(CRT)

提问:

  • C++进入点是main()吗?
  • 什么代码比main()更早被执行?
  • 什么代码在main()结束后才被执行?
  • 为什么上述代码可以如此行为?
  • Heap的结构如何?
  • I/O的结构如何?

 在windows环境下,使用VC6进行开发,我们写下以下代码(启动码函数):

#include <windows.h>
int MyStartup(void)
{
    int a=10;
    HANDLE crtHeap=HeapCreate(HEAP_NO_SERIALIZE,0x010,4000*1024);
    int *p=(int*)HeapAlloc(crtHeap,HEAP_ZERO_MEMORY,0X010);
    int i,j;
    
    for(i=0;i<100;i++)
    {
        for(j=0;j<100;j++,p++)
        {
            *p=i*100+(j+1);
        }
    }    

    MessageBoxA(NULL,p,"abcd",MB_OK);
    return 0;
}

我们的程序将从MyStartup()函数启动,并且不会调用main函数(因为我们没写。。)

 

在linux环境下,我们编写了两个函数,使用GCC进行编译:

$ cat entrypoint.c

int blabla(){ printf("Yes it works!\n"); exit(0); }
int main(){ printf("not called!\n");}

$ gcc entrypoint.c -e blala    //-e:告诉使用balala函数作为进入点

$ ./a.out
Yes it works!                 //main函数并没有执行

 

总结:

任何的c/c++程序,在main函数之前,有一个启动函数,你的main函数必须由启动码函数调用起来。启动码也是最早执行的函数。

 

默认的startup code在哪里,main()生前和死后的call stack

我们以VC6为例:主要分为9个点来分析:

 

 

1.heap_init()——Startup的首要管理工具

内存块:1.从何处来?2.大小几何?3.回收至何处?

SBH(Small Block Heap):应付CRT本身以及main进去之后的所有内存(size=1024=1k)。

如果客户要的区块大小要小于sbh_threshold(size=1016,加上图中的上下的00000131(各占4个字节),1016+8=1024,即1K),将从sbh内部去申请内存。反之,使用HeapAlloc(win提供的API函数),让操作系统提供服务。

因此,内存小于等于1K的,VC6认为它足够小,它将使用SBH去服务它。反之,若大于1K,将有操作系统那些"池塘"(HeapAlloc等函数)来提供。(内存块从哪里来)

HeapAlloc:HeapAlloc是Windows提供的API,在进程初始化的时候,系统会在进程的地址空间中创建1M大小的堆,称为默认堆(Default Heap),该大小为默认值,可以通过/HEAP连接器开关进行修改。用户也可以通过HeapCreate创建额外的堆,堆的使用可以更有效的进行内存管理,避免线程同步的开销以及快速的释放内存等。

我们可以向操作系统(win)要求A这么一大块内存,B这么一大块内存,C这么一大块内存,我们可以根据不同用途从不同的内存块获取。若需要A功能就从A里面拿,若需要B功能就从B里面拿。

SBH初始化:

给我一块区域,多大呢?4096(初始值,可弹性增长)。我们把它取名位crtheap。

heap_init在做初始化呢,申请了16个Headers(可在内存管理章节详细了解)。

每个Header的内部情况:

 

参考:博览网——侯捷 - C++ Startup 揭密:C++ 程序的生前和死后

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值