分类: C/C++
2011-05-09 12:17:10
我们在用VC6.0的时候可能会遇到如下的问题: LINK : LNK6004: Debug/aoe.exe not found or not built by the last incremental link; performing full link 我的程序是VC6.0下编的, 这种情况很可能是因为没有使用预编译,所以每次都全部链接了。假如每次都这样,修改项目属性中的“链接器”-“常规”-“启用增量链接”选项为“是(/INCREMENTAL)”。 还有经常遇到的碰到的问题如下: 第一个debug文件夹编译后不会有exe文件生成 ,第二个debug文件夹编译后会有exe文件生成。 【解决方法如下】 假如出现上述错误,可以使用clean,然后第一个文件就剩了BuildLog.htm文件 , 而第二个文件夹还存在aoe.ilk文件,删除这个文件,再编译即可怀疑这个问题是clean的一个bug,没有清除 aoe.ilk(关键文件啊)文件。 接下来了解一下Incremental Link Table。 那么什么是Incremental Link Table呢? 想想如果我们自己要做编译器(compiler)和连接器(linker),当然希望编译连接运行得越快越好,同时也希望产生的二进制代码也是又快又小,上帝是公平的,鱼与熊掌不可兼得,所以我们 自然想到用两种build方式,一种Release,编译慢一些,但是产生的二进制代码紧凑精悍,一种Debug,编译运行快,产生的代码臃肿一点没关系,Debug版本嘛,就是指望程序员在开发的时 候反复的build,为了不浪费程序员的时候,要想尽办法让编译连接速度变快。 假如一个程序有连续两个foo和bar (所谓连续,就是他们编译连接之后函数体连续存放), foo入口位置在0x0400,长度为0x200个字节,那么bar入口就应该在0x0600 = 0x0400+0x0200。程序 员在开发的时候总是频繁的修改code然后build,假如程序员在foo里面增加了一些内容,现在foo函数体占0x300个字节了,bar的入口也就只好往后移0x100变成了0x0700,这样就有一个问题 ,如果foo在程序中被调用了n次,那么linker不得不修改这n个函数调用点,虽然linker不嫌累,但是link时间长了,程序员会觉得不爽。所以MSVC在Debug版的build,不会让各个函数体之间 这么紧凑,每个函数体后都有padding(全是汇编代码int 3,作用是引发中断,这样因为古怪原因运行到不该运行的padding部分,会发生异常),有了这些padding,就可以一定程度上缓解 上面提到的问题,不过当函数增加内容太多超过padding,还是有问题,怎么办呢?MSVC在Debug build中用上了Incremental Link Table, ILT其实就是一串jmp语句,每个jmp语句对应一个 函数,jmp的目的地就是函数的入口点,和没有ILT的区别是,现在对函数的调用不是直接call到函数入口点了,而是call到ILT中对应的位置,而这个位置上什么也不做,直接jmp到函数中去 。这样的好处是,当一个函数入口地址改变时,只要修改ILT中对应值就搞定了,用不着修改每一个调用位置,用一个冗余的ITL把时间复杂度从O(n)将为O(1),值得,当然Debug版的二进制文 件会稍大稍慢,Release版不会用上ILT。 下面是有关的英语文献,有兴趣的可以看看啊: /INCREMENTAL (Link Incrementally) The /INCREMENTAL option controls how the linker handles incremental linking. By default, the linker runs in incremental mode. To override a default incremental link, specify /INCREMENTAL:NO. An incrementally linked program is functionally equivalent to a program that is nonincrementally linked. However, because it is prepared for subsequent incremental links, an incrementally linked executable (.exe) file or dynamic-link library (DLL): Is larger than a nonincrementally linked program because of padding of code and data. (Padding allows the linker to increase the size of functions and data without recreating the .exe file.) then links the program nonincrementally. Certain options and situations override /INCREMENTAL. Most programs can be linked incrementally. However, some changes are too great, and some options are incompatible with incremental linking. LINK performs a full link if any of the following options are specified: Link Incrementally is not selected (/INCREMENTAL:NO) /INCREMENTAL is implied when /DEBUG is specified. Additionally, LINK performs a full link if any of the following situations occur: The incremental status (.ilk) file is missing. (LINK creates a new .ilk file in preparation for subsequent incremental linking.) Open the project's Property Pages dialog box. For details, see Setting Visual C++ Project Properties. 这个问题不难了吧。 我的百度空间: http://hi.baidu.com/heihei_shaweiwei/blog/item/eec5a3de6bb28c0462279805.h |