基於Visual Studio開發C++/Qt項目的錯誤解決筆記


開發環境:win7/10;VS201/2015;Qt4.8.6/5.7.1;CMake

1、error LNK2005: "double * X" 已經在 main.obj 中定義;

參考1:https://www.cnblogs.com/MuyouSome/p/3332699.html   https://blog.csdn.net/yan_less/article/details/73149578

1.重復定義全局變量。可能存在兩種情況:  
 A、對於一些初學編程的程序員,有時候會以為需要使用全局變量的地方就可以使用定義申明一下。其實這是錯誤的,全局變量是針對整個工程的。
  正確的應該是在一個CPP文件中定義如下:
  int   g_Test;
  那么在使用的CPP文件中就應該使用:
  extern   int   g_Test
  即可,如果還是使用int   g_Test,那么就會產生LNK2005錯誤,一般錯誤錯誤信息類似:
  *.obj   error   LNK2005   int   book   c?   already   defined   in   *.obj
  切記的就是不能給變量賦值否則還是會有LNK2005錯誤。  
  這里需要的是“聲明”,不是“定義”!根據C++標准的規定,一個變量是聲明,必須同時滿足兩個條件,否則就是定義:  
  (1)聲明必須使用extern關鍵字
  (2)不能給變量賦初值  
  所以,下面的是聲明:  
    extern   int   a;  
  下面的是定義  
    int   a;  
    int   a   =   0;  
    extern   int   a   =0;  
  B、對於那么編程不是那么嚴謹的程序員,總是在需要使用變量的文件中隨意定義一個全局變量,並且對於變量名也不予考慮,這也往往容易造成變量名重復,而造成LNK2005錯誤。  

2.頭文件的包含重復。
  往往需要包含的頭文件中含有變量、函數、類的定義,在其它使用的地方又不得不多次包含之,如果頭文件中沒有相關的宏等防止重復鏈接的措施,那么就會產生LNK2005錯誤。解決辦法是在需要包含的頭文件中做類似的處理:
  #ifndef   MY_H_FILE       //如果沒有定義這個宏  
  #define   MY_H_FILE       //定義這個宏  
  …….       //頭文件主體內容  
  …….  
  #endif  
  上面是使用宏來做的,也可以使用預編譯來做,在頭文件中加入:  
  #pragma   once  
  //頭文件主體  
 3.使用第三方的庫造成的。
  這種情況主要是C運行期函數庫和MFC的庫沖突造成的。具體的辦法就是將那個提示出錯的庫放到另外一個庫的前面。另外選擇不同的C函數庫,可能會引起這個錯誤。微軟和C有兩種C運行期函數庫,一種是普通的函數庫:LIBC.LIB,不支持多線程。另外一種是支持多線程的:msvcrt.lib。如果一個工程里,這兩種函數庫混合使用,可能會引起這個錯誤,一般情況下它需要MFC的庫先於C運行期函數庫被鏈接,因此建議使用支持多線程的msvcrt.lib。所以在使用第三方的庫之前首先要知道它鏈接的是什么庫,否則就可能造成LNK2005錯誤。如果不得不使用第三方的庫,可以嘗試按下面所說的方法修改,但不能保證一定能解決問題,前兩種方法是微軟提供的:  
  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等其他庫,逐一嘗試。  


綜上,你應該把要申明的變量放在一個1.h中,然后在其中寫如下代碼

#pragma once 
int i=0;

然后新建的.cpp文件中包含#include<1.h>

參考2:https://blog.csdn.net/zhaoyong26/article/details/84635383

經過仔細看代碼發現,一個全局變量在一個頭文件中定義,比如:head1.h中定義了全局變量int a = 10;

在一個類的頭文件class.h中包含了頭文件head1.h如:include "head1.h"

於是將include "head1.h"從class.h中移到了class.cpp中,問題解決。

分析,因為class.cpp中include "class.h"class.h中include "head1.h",發現沒,會造成head1.h的重復引用,雖然用pragma等也無法解決,移到class.cpp中,它生成obj文件時,只引用一次,問題解決。

 2、warning C4482: 使用了非標准擴展: 限定名中使用了枚舉

來源: 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:
使用了非標准擴展: 限定名中使用了枚舉“enum”
當引用類型內的枚舉時,無需指定枚舉的名稱。
文件范圍的枚舉定義相當於常量,也不需要限定名。
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捕獲了事件處理程序引發的異常(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成員函數 //定義一個派生類,該派生類重寫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) { // 日志或某些恢復過程 } catch (...) { // 日志或某些恢復過程 } return done; } //當捕獲到異常時,記錄日志,屏幕上的彈出窗口等,並通知異常發生,如果可以處理異常,則執行恢復處理。對於屏幕上的彈出窗口,通常使用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的官網下載壓縮包,地址:https://imagemagick.org/script/download.php

根據平台下載相對應的壓縮包,如Windows下載ImageMagick-7.0.11-8-Q16-HDRI-x64-dll.exe

2、安裝ImageMagick

3、在Qt的資源文件夾下(Qt調用資源的目錄)新建 ImageMagick-Fix-PNG.bat 文件

打開后編輯內容:

@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、保存並執行.bat。

5、重新編譯項目,警告消除!

 5、warning C4273: dll 鏈接不一致

參考:https://blog.csdn.net/qc530167365/article/details/94559537

//在編譯Dll文件的時候遇到dll 鏈接不一致的問題,頭文件如下:

    #ifdef TESTDLLEXPORT
    #define DLLEXPORT __declspec(dllexport)
    #else
    #define DLLEXPORT __declspec(dllimport)
    #endif
     
    #ifdef __cplusplus
    extern "C" {
    #endif
     
    DLLEXPORT void test();
     
    #ifdef __cplusplus
    }
    #endif

//雖然外部程序可以正常調用test();但鏈接不一致的根源是第一行TESTDLLEXPORT沒有預定義

//解決辦法:項目屬性-> C/C++ -> 預處理器 ->預處理器定義,添加TESTDLLEXPORT即可。
//如果用CMake構建,還要注意[add_definitions(-DTESTDLLEXPORT)];
//另外一定要注意該變量的【 大 小 寫 】!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM