前言:如何自定Startup code(CRT)
提问:
C++进入点是main()吗?
什么代码比main()更早被执行?
什么代码在main()结束后才被执行?
为什么上述代码可以如此行为?
Heap的结构如何?
I/O的结构如何?
在windows环境下,使用VC6进行开发,我们写下以下代码(启动码函数):
#include
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的内部情况:
————————————————
版权声明:本文为CSDN博主「Jeff_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_40539125/article/details/100631710