[英]C++ Segmentation fault at std::map::insert
我正在嘗試自學C ++(實際上我應該說重新學習,但是在一年前我對編碼一無所知時,我第一次學習了它,所以不算在內),我正在做我的第一個項目完成在線教程后。 我認為,由於我擁有良好的C#和VB.Net背景,因此我不妨嘗試更大一點的東西,但不要太大。 在開始之前,我將使用Code :: Blocks作為我的IDE和該IDE中的默認編譯器(我相信它是MinGW)。 所以這是我的事情:我有一個ChromaTest項目(對於想知道名稱的人使用Razer Chroma SDK)是一個控制台應用程序,還有一個ChromaTestDLL項目,這是(您猜到了)一個DLL(我決定做一個DLL來學習如何同時做,因為稍后我可能會在GUI項目中使用一些代碼)。 問題是嘗試插入地圖時出現“細分錯誤”錯誤。 這是相關的代碼:
在ChromaTestDLL項目中
MyChroma.h (MyChroma類的標題)
#ifndef MYCHROMA_H
#define MYCHROMA_H
#include <map>
#include <windef.h>
#include "RzChromaSDKTypes.h"
#include <string>
#include "Template.h"
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
using namespace std;
#ifdef __cplusplus
extern "C"
{
#endif
class DLL_EXPORT MyChroma
{
public:
MyChroma();
bool Init();
std::map<char, COLORREF> GetColorMapping();
void SetColorMapping(char key, COLORREF color);
void AssignToKeyBoard();
void SetColorFromString(string s, COLORREF color);
~MyChroma();
protected:
std::map<char, COLORREF>* _ColorMapping;
ChromaSDK::Keyboard::RZKEY KeyFromChar(char keyChar);
My_Chroma_Implementation* Chroma;
private:
};
#ifdef __cplusplus
}
#endif
#endif // MYCHROMA_H
MyChroma.cpp (MyChroma類的相關實現)
#include "MyChroma.h"
#include "Template.h"
#include <iostream>
MyChroma::MyChroma()
{
_ColorMapping = new std::map<char, COLORREF>();
}
std::map<char, COLORREF> MyChroma::GetColorMapping() { return *_ColorMapping; }
void MyChroma::SetColorMapping(char key, COLORREF color){
if (_ColorMapping->count(key) == 0)
_ColorMapping->insert(std::make_pair(key, color)); //This where the error happens
else
(*_ColorMapping)[key] = color;
}
MyChroma::~MyChroma() {
delete Chroma;
delete _ColorMapping;
}
//Other implementations omitted
在ChromaTest項目中
MyChroma.h (導入MyChroma類的標題,與ChromaTestDll中的類稍有不同,基本上只包含公共成員)
#ifndef MYCHROMA_H
#define MYCHROMA_H
#include <map>
#include <windef.h>
#include <string>
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
using namespace std;
#ifdef __cplusplus
extern "C"
{
#endif
class DLL_EXPORT MyChroma
{
public:
MyChroma();
bool Init();
std::map<char, COLORREF> GetColorMapping();
void SetColorMapping(char key, COLORREF color);
void AssignToKeyBoard();
void SetColorFromString(string s, COLORREF color);
~MyChroma();
};
#ifdef __cplusplus
}
#endif
#endif // MYCHROMA_H
Main.cpp (主應用代碼)
#include <iostream>
#include "MyChroma.h"
#include <wingdi.h>
using namespace std;
int main()
{
MyChroma test = MyChroma();
bool result = test.Init();
cout << (result ? "Initialized\n" : "Failed to initialize Razer Chroma");
cout << "Setting color";
if (result){
test.SetColorMapping('a', RGB(255,0, 0)); //This call goes in the DLL where I said it failed earlier.
test.SetColorMapping('a', RGB(0,0,255));
}
return 0;
}
很抱歉這個冗長的代碼(請告訴我這里是否有我可以刪除的內容)。 任何人都可以在那里發現任何錯誤,我不會對此感到驚訝,因為它將與指針相關聯,這可能是花了我最多時間來理解的概念。 最初,我沒有將映射放在指針和堆上,但是將另一個變量更改為較早的變量似乎已經解決了另一個問題,因此我想嘗試一下。 可悲的是,當我也沒有將地圖放到堆上時,我遇到了幾乎相同的錯誤。
順便說一句,任何人都可以向我解釋一下堆和棧之間的區別是什么,為什么我要經歷(危險的)麻煩將變量存儲在堆中(包括指針,刪除和全部),而不是在棧上,什么時候應該使用堆,什么時候不應該使用堆。
根據您問題中的信息:
DLL中的已編譯代碼似乎在其頭文件中聲明了一個MyChroma
類,其中包含一堆內部類成員。
然后,您的主應用程序使用完全不同的頭文件,該頭文件定義了一個名為MyChroma
的類,該類除去了其類成員。
然后,您的主應用程序根據其在頭文件中看到的內容實例化MyChroma
類。
那是行不通的。 由於您的主應用程序對這些類成員一無所知,因此它實例化的實際類太小。
並實例化堆棧上的一個類。
然后,構造函數來自DLL,后者認為該類包含所有其他這些類成員。
DLL中的構造函數將嘗試對其進行初始化。
在堆棧上。
你好堆棧損壞。
答案很簡單,就是“不要做你所做的事情”。 這是未定義的行為。 您編譯的引用特定類的所有內容都必須看到該類的相同聲明(和內聯方法定義)。
句號
沒有例外。
好吧,如果有足夠的經驗,在針對特定的C ++實現時,可以安全地執行類似的操作,但實際情況並非如此。
在此之前,有一些方法可以隱藏庫提供的類的內部實現細節,但這不是您要做的。 安全的方法是使用PIMPL設計模式 。
您也不應做其他一些事情。 這與手頭的問題沒有直接關系,但是可以避免其他一些常見的陷阱,這些陷阱可以在沒有事先警告的情況下將地毯從腳下拉出:
不要使用use namespace std; 。 特別是在頭文件中。 完全忘記C ++語言中存在類似的東西。
您所有的課程也應遵循“三規則” 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.