首页
论坛
课程
招聘
[旧帖] [原创]跑在main之前 0.00雪花
2011-5-27 15:09 2241

[旧帖] [原创]跑在main之前 0.00雪花

2011-5-27 15:09
2241
通常这是一个面试题,如何让一段代码跑在main()函数前面。一个熟练的C++开发者能够轻易给出答案,即 静态初始化

在C里面又如何呢,有没有办法做到这点?下面讲一个VC里的方法。

int initBeforeMain()
{
 printf( "initBeforeMain (%p)\r\n", initBeforeMain );
 return 0;
}

int init2BeforeMain()
{
 printf( "init2BeforeMain (%p)\r\n", init2BeforeMain );
 return 0;
}

int initBreak()
{
 DebugBreak();
 return 0;
}

typedef int (*pInit)();

// for C

// put following table between __xi_a and __xi_z

#pragma data_seg( ".CRT$XIU" )
pInit start[] = {initBeforeMain, init2BeforeMain, initBreak, };
#pragma data_seg()

// for C++

// put following table between __xc_a and __xc_z

#pragma data_seg( ".CRT$XCU" )
pInit start2[] = {initBeforeMain, init2BeforeMain, initBreak, };
#pragma data_seg()

// for C

// put following pointer between __xi_a and __xi_z but after start

#pragma data_seg( ".CRT$XIU" )
pInit start3 = initBreak;
#pragma data_seg()

int main( int argc, char* argv[] ) {}

在调试器里执行一下,看看效果如何,有没有给你surprise。

解释上面代码之前先说一些背景知识,众所周知,开发者所写的入口函数一般都不是真正的入口,编译器会提供自己的入口函数,再调用开发者的。逻辑很简单,如下:

CRTEntry() { {__CRTInit}; UserEntry(); {__CRTUninit}; }

__CRTInit中做一些初始化工作,包括C库,C的初始化函数,C++库,C++的初始化函数等。C和C++分别有一张表来保存初始化函数指针,每个表又使用2个指针来明确范围,__CRTInit会依次调用这2个表中的函数。

C初始化函数表:[__xi_a, __xi_z)

C++初始化函数表: [__xc_a, __xc_z)

现在对照代码注释,就会明白上述那段代码的作用。通过特殊的段名称“.CRT$XIU”,“.CRT$XCU”,链接器会把start表放在“C初始化函数表”中,类似这样,[__xi_a, ..., start, ..., __xi_z),同理,start2表会被链接器放在“C++初始化函数表”中,象这样,[__xc_a, ..., start2, ..., __xc_z),而最后一个start3变量所对应的指针还是会被放在“C初始化函数表”中,在上面例子中,会放在start之后,[__xi_a, ..., start, ..., start3, ..., __xi_z),这里的start3的位置即函数指针initBreak的位置。

最初发布在这:http://user.qzone.qq.com/31731705/blog/1302771059,包含一些贴图的结果,这贴图不方便,因此只写文字了,想看图的可以访问链接。

[2023春季班]《安卓高级研修班(网课)》月薪两万班招生中~

收藏
点赞0
打赏
分享
最新回复 (9)
雪    币: 47
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tusiji 活跃值 2011-5-27 15:13
2
0
天天学习,好好向上
雪    币: 5815
活跃值: 活跃值 (859)
能力值: ( LV13,RANK:283 )
在线值:
发帖
回帖
粉丝
littlewisp 活跃值 2 2011-5-27 15:39
3
0
先想到的是tls
雪    币: 232
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
xulay 活跃值 1 2011-5-27 15:39
4
0
简单的问题说得如此复杂。
摆桃花阵的教程不看也罢。
雪    币: 123
活跃值: 活跃值 (16)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
weizehua 活跃值 1 2011-5-27 16:59
5
0
设置entry ,想怎么跑就怎么跑,LZ还要多多学习^_^
雪    币: 78
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
ronging 活跃值 2011-5-27 18:32
6
0
我讲的内容是“跑在main之前”,楼上说的是设置程序entrypoint,这有关系嘛?
雪    币: 1898
活跃值: 活跃值 (545)
能力值: ( LV13,RANK:420 )
在线值:
发帖
回帖
粉丝
demoscene 活跃值 7 2011-5-27 18:51
7
0
在<软件调试>里看过,当时试了下效果,没有深入研究
雪    币: 238
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
alexy 活跃值 2011-5-27 19:11
8
0
个人认为这个不是攻防的范畴。

对于程序员而言,了解这些还是有意义的。
雪    币: 473
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
comewisdom 活跃值 2011-5-27 20:54
9
0
路过路过路过...............
雪    币: 214
活跃值: 活跃值 (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
pianoid 活跃值 2011-5-27 21:22
10
0
5L说的设置entry应该是指#pragma comment(linker,"/entry:myMainCrtStartup"),不过这样也挺好玩的。
游客
登录 | 注册 方可回帖
返回