基于Visual Studio開發(fā)C++/Qt項(xiàng)目的錯(cuò)誤解決筆記
開發(fā)環(huán)境:win7/10;VS201/2015;Qt4.8.6/5.7.1;CMake
1、error LNK2005: "double * X" 已經(jīng)在 main.obj 中定義;
參考1:http://www.rzrgm.cn/MuyouSome/p/3332699.html https://blog.csdn.net/yan_less/article/details/73149578
1.重復(fù)定義全局變量。可能存在兩種情況: A、對于一些初學(xué)編程的程序員,有時(shí)候會以為需要使用全局變量的地方就可以使用定義申明一下。其實(shí)這是錯(cuò)誤的,全局變量是針對整個(gè)工程的。 正確的應(yīng)該是在一個(gè)CPP文件中定義如下: int g_Test; 那么在使用的CPP文件中就應(yīng)該使用: extern int g_Test 即可,如果還是使用int g_Test,那么就會產(chǎn)生LNK2005錯(cuò)誤,一般錯(cuò)誤錯(cuò)誤信息類似: *.obj error LNK2005 int book c? already defined in *.obj 切記的就是不能給變量賦值否則還是會有LNK2005錯(cuò)誤。 這里需要的是“聲明”,不是“定義”!根據(jù)C++標(biāo)準(zhǔn)的規(guī)定,一個(gè)變量是聲明,必須同時(shí)滿足兩個(gè)條件,否則就是定義: (1)聲明必須使用extern關(guān)鍵字 (2)不能給變量賦初值 所以,下面的是聲明: extern int a; 下面的是定義 int a; int a = 0; extern int a =0; B、對于那么編程不是那么嚴(yán)謹(jǐn)?shù)某绦騿T,總是在需要使用變量的文件中隨意定義一個(gè)全局變量,并且對于變量名也不予考慮,這也往往容易造成變量名重復(fù),而造成LNK2005錯(cuò)誤。 2.頭文件的包含重復(fù)。 往往需要包含的頭文件中含有變量、函數(shù)、類的定義,在其它使用的地方又不得不多次包含之,如果頭文件中沒有相關(guān)的宏等防止重復(fù)鏈接的措施,那么就會產(chǎn)生LNK2005錯(cuò)誤。解決辦法是在需要包含的頭文件中做類似的處理: #ifndef MY_H_FILE //如果沒有定義這個(gè)宏 #define MY_H_FILE //定義這個(gè)宏 ……. //頭文件主體內(nèi)容 ……. #endif 上面是使用宏來做的,也可以使用預(yù)編譯來做,在頭文件中加入: #pragma once //頭文件主體 3.使用第三方的庫造成的。 這種情況主要是C運(yùn)行期函數(shù)庫和MFC的庫沖突造成的。具體的辦法就是將那個(gè)提示出錯(cuò)的庫放到另外一個(gè)庫的前面。另外選擇不同的C函數(shù)庫,可能會引起這個(gè)錯(cuò)誤。微軟和C有兩種C運(yùn)行期函數(shù)庫,一種是普通的函數(shù)庫:LIBC.LIB,不支持多線程。另外一種是支持多線程的:msvcrt.lib。如果一個(gè)工程里,這兩種函數(shù)庫混合使用,可能會引起這個(gè)錯(cuò)誤,一般情況下它需要MFC的庫先于C運(yùn)行期函數(shù)庫被鏈接,因此建議使用支持多線程的msvcrt.lib。所以在使用第三方的庫之前首先要知道它鏈接的是什么庫,否則就可能造成LNK2005錯(cuò)誤。如果不得不使用第三方的庫,可以嘗試按下面所說的方法修改,但不能保證一定能解決問題,前兩種方法是微軟提供的: A、選擇VC菜單Project->Settings->Link->Catagory選擇Input,再在Ignore libraries 的Edit欄中填入你需要忽略的庫,如:Nafxcwd.lib;Libcmtd.lib。然后在Object/library Modules的Edit欄中填入正確的庫的順序,這里需要你能確定什么是正確的順序,呵呵,God bless you! B、選擇VC菜單Project->Settings->Link頁,然后在Project Options的Edit欄中輸入/verbose:lib,這樣就可以在編譯鏈接程序過程中在輸出窗口看到鏈接的順序了。 C、選擇VC菜單Project->Settings->C/C++頁,Catagory選擇Code Generation后再在User Runtime libraray中選擇MultiThread DLL等其他庫,逐一嘗試。 綜上,你應(yīng)該把要申明的變量放在一個(gè)1.h中,然后在其中寫如下代碼 #pragma once int i=0; 然后新建的.cpp文件中包含#include<1.h>
參考2:https://blog.csdn.net/zhaoyong26/article/details/84635383
經(jīng)過仔細(xì)看代碼發(fā)現(xiàn),一個(gè)全局變量在一個(gè)頭文件中定義,比如:head1.h中定義了全局變量int a = 10; 在一個(gè)類的頭文件class.h中包含了頭文件head1.h如:include "head1.h" 于是將include "head1.h"從class.h中移到了class.cpp中,問題解決。 分析,因?yàn)閏lass.cpp中include "class.h",class.h中include "head1.h",發(fā)現(xiàn)沒,會造成head1.h的重復(fù)引用,雖然用pragma等也無法解決,移到class.cpp中,它生成obj文件時(shí),只引用一次,問題解決。
2、warning C4482: 使用了非標(biāo)準(zhǔn)擴(kuò)展: 限定名中使用了枚舉
來源: http://blog.sina.com.cn/s/blog_6dc6b05d0100r3nh.html http://dev.firnow.com/course/3_program/c++/cppsl/2008619/126863.html
MSDN: compiler warning (level 1) C4482 warning description: 使用了非標(biāo)準(zhǔn)擴(kuò)展: 限定名中使用了枚舉“enum” 當(dāng)引用類型內(nèi)的枚舉時(shí),無需指定枚舉的名稱。 文件范圍的枚舉定義相當(dāng)于常量,也不需要限定名。 example: C4482(MS Visual Studio) // C4482.cpp // compile with: /c /W1 struct S { enum E { a }; }; int i = S::E::a; // C4482 int j = S::a; // OK NOTE: warring C4482: nonstandard extension used: enum **** used in qualified name enumeration: 1. Standard C++ does not allow enumeration names to be used as scopes (GCC: error) Visual C++ is half-hearted on the matter. (warrning) 2. C# support enumeration names as scopes. Workaround: (for MS Visual Stdio) if you want to get rid of those obnoxious error message and you’re using MS Visual Studio, encompass your statement in #pragma directives. For example, #progma warning(push) #progma warning(disable : 4482) ... (your statement here) ... #progma warning(pop) That tells the compiler not to report the C4482 warning for the code within the block. You are essentially saying to the compiler, “Yes, I’m doing this intentionally. I know it’s not comply with the standard, but I want it done anyway. So build my project and quit your whining!”
3、Qt捕獲了事件處理程序引發(fā)的異常(Qt has caught an exception thrown from an event handler. Throwing exceptions from an event handler is not supported in Qt. You must reimplement QApplication::notify() and catch all exceptions there.)
來源: https://stackoverflow.com/questions/10075792/how-to-catch-exceptions-in-qt http://www.02.246.ne.jp/~torutk/cxx/qt/QtMemo.html
//(未測試!)
//繼承QApplication并重寫notify成員函數(shù) //定義一個(gè)派生類,該派生類重寫Qt消息中的QApplication :: notify。 //MyApplication.h #include <QApplication> class MyApplication : public QApplication { public: MyApplication(int& argc, char** argv); bool notify(QObject* receiver, QEvent* event); };
//MyApplication.cpp #include "MyApplication.h" #include <exception> MyApplication::MyApplication(int& argc, char** argv) : QApplication(argc, argv) {} bool MyApplication::notify(QObject* receiver, QEvent* event) { bool done = true; try { done = QApplication::notify(receiver, event); } catch (const std::exception& ex) { // 日志或某些恢復(fù)過程 } catch (...) { // 日志或某些恢復(fù)過程 } return done; } //當(dāng)捕獲到異常時(shí),記錄日志,屏幕上的彈出窗口等,并通知異常發(fā)生,如果可以處理異常,則執(zhí)行恢復(fù)處理。對于屏幕上的彈出窗口,通常使用QMessageBox :: critical(...)。
4、Qt :libpng warning: iCCP: known incorrect sRGB profile警告
參考:https://blog.csdn.net/u012803067/article/details/77370275
Qt :libpng warning: iCCP: known incorrect sRGB profile警告信息之解決方法 1、從ImageMagick的官網(wǎng)下載壓縮包,地址:https://imagemagick.org/script/download.php 根據(jù)平臺下載相對應(yīng)的壓縮包,如Windows下載ImageMagick-7.0.11-8-Q16-HDRI-x64-dll.exe 2、安裝ImageMagick 3、在Qt的資源文件夾下(Qt調(diào)用資源的目錄)新建 ImageMagick-Fix-PNG.bat 文件 打開后編輯內(nèi)容: @echo off echo ImageMagick fix libpng warning: iCCP: Not recognizing known sRGB profile ...... echo Search PNG in subdirs and process ... set fn=C:\YOU-SETUP-ImageMagick-PATH\convert.exe for /f "tokens=*" %%i in ('dir/s/b *.png') do "%fn%" "%%i" -strip "%%i" pause 4、保存并執(zhí)行.bat。 5、重新編譯項(xiàng)目,警告消除!
5、warning C4273: dll 鏈接不一致
參考:https://blog.csdn.net/qc530167365/article/details/94559537
//在編譯Dll文件的時(shí)候遇到dll 鏈接不一致的問題,頭文件如下: #ifdef TESTDLLEXPORT #define DLLEXPORT __declspec(dllexport) #else #define DLLEXPORT __declspec(dllimport) #endif #ifdef __cplusplus extern "C" { #endif DLLEXPORT void test(); #ifdef __cplusplus } #endif //雖然外部程序可以正常調(diào)用test();但鏈接不一致的根源是第一行TESTDLLEXPORT沒有預(yù)定義 //解決辦法:項(xiàng)目屬性-> C/C++ -> 預(yù)處理器 ->預(yù)處理器定義,添加TESTDLLEXPORT即可。 //如果用CMake構(gòu)建,還要注意[add_definitions(-DTESTDLLEXPORT)]; //另外一定要注意該變量的【 大 小 寫 】!!!
6、LINK : fatal error LNK1104: 無法打開文件“xxx.lib”
參考:https://blog.csdn.net/hhhuang1991/article/details/84060977
1、如果使用Qt Creator,配置.pro構(gòu)建項(xiàng)目,注意以下內(nèi)容: UNIX系統(tǒng)中,用-l標(biāo)識庫名稱,-L標(biāo)識庫路徑; Windows系統(tǒng)中,導(dǎo)入lib庫時(shí),采用全路徑的方式: // 使用相對路徑,采用系統(tǒng)變量,$$PWD當(dāng)前工程目錄 LIBS += $$PWD/3rdparty/lib/xxx.lib // 或 使用絕對路徑 如果路徑中沒有空格 LIBS += D:/Myproject/3rdparty/lib/xxx.lib // 如果路徑中有空格,需用雙引號括起來 LIBS += "D:/My project/3rdparty/lib/xxx.lib" 注意:修改.pro中的路徑后,需要對項(xiàng)目再次“執(zhí)行qmake”,“重新構(gòu)建”,否則Qt Creator會保持之前的狀態(tài)。 2、如果使用VS,構(gòu)建項(xiàng)目: 在VS解決方案資源管理器中選中主項(xiàng)目,右鍵->屬性,進(jìn)行配置(根據(jù)生成方式Debug或Release略有不同): 屬性->配置屬性->鏈接器->輸入: Debug方式附加依賴項(xiàng):D:/Myproject/3rdparty/lib/xxxd.lib Release方式附加依賴項(xiàng):D:/Myproject/3rdparty/lib/xxx.lib 如還需配置第三方庫頭文件包含及預(yù)處理器標(biāo)識: (1)屬性->配置屬性->C/C++->常規(guī),附加包含目錄:D:/Myproject/3rdparty/include/xxx (2)屬性->C/C++->預(yù)處理器->預(yù)處理器定義:添加該庫的預(yù)處理器標(biāo)識符。(如QWT_DLL,見qwt_global.h)

浙公網(wǎng)安備 33010602011771號