由於我最近調整了一下 Jimi 的文件結構,導致出現了一個 LNK4042 的 warning,我並沒有很重視,這個 warning 導致出現了一些錯誤。
我調試了幾個小時,一開始並沒有想到是這個 warning 造成的,以為是我改代碼改出來的問題(因為最近做了大量調整),特此記錄一下。
我在調整代碼結構的時候,出現了這麼兩個文件 assert.cpp 和 assert.c,之前分別叫 jimi_assert.cpp 和 jimic_assert.c,所以相安無事,
沒有出現這個問題。而且由於是定義的 assert 函數,所以這個問題在 Release 版下不會有問題,在編譯 Debug 版的時候才會出現,提示如下:
1>G:\Project\OpenSrc\Jimi_Root\Jimi\gen\tmp\vc2013\Jimi_static\x86-Debug\assert.obj : warning LNK4042: 對象被多次指定;已忽略多余的指定
這會導致下面這個錯誤:
這是 C 裡用到的 jimic_assert() 的鏈接錯誤,有時候,還會報 C++ 裡的 jimi::assertion_failure() 的鏈接錯誤,
即 jimi_assert(),這兩個錯誤出現的機率有一定隨機性(只會出現一個),所以也導致我調試了幾個小時……。
我們來 Google 一下 “LNK 4042”,在 CSDN 查到一個中文的:VS2010 警告 LNK4042 截圖如下:
Visual Studio 2010's strange “warning LNK4042” ,
還有 MSDN: Linker Tools Warning LNK4042 裡提到的: Visual Studio 2010 & 2008 can't handle source files with identical names in different folders? ,
原來造成這個 warning 和錯誤的原因是:assert.c 和 assert.cpp 生成的 obj 文件名重疊了,導致編譯的時候只能鏈接其中一個,因為另外一個因為文件名一樣被覆蓋掉了。
最簡單的解決辦法就是讓兩個文件的文件名不一樣,我把 assert.c 改名為 assert-c.c 後,就解決了。
但是有些時候的確是有可能在不同的文件夾下面使用相同的文件名的,所以這種方法不能一勞永逸。這個問題是因為默認的情況下,所有的 obj 都生成到同一個文件夾裡,所以可以單獨的指定某個文件的 obj 生成路徑,這樣就不會被覆蓋了。在VS裡選定你要改的文件,然後右鍵->點“屬性”,示例如下:
把 對象文件名 由:Obj$(IntDir) 改為 Obj$(IntDir)\你想修改的路徑 或 obj文件名,例如上圖中的:Obj$(IntDir)\jimic_assert\ 或者 Obj$(IntDir)\jimic_assert.obj。、
有一點需要注意的是,最好選擇“所有配置”,把 "Release" 和 "Debug" 或 其他配置都一起改了。
當然,想簡單一點,還是改文件名比較快。。。
如果還有什麼疑問,可以去看看那兩個 stackoverflow.com 的帖子。
(完)