簡體   English   中英

在std :: map :: insert的C ++分段錯誤

[英]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;
}

很抱歉這個冗長的代碼(請告訴我這里是否有我可以刪除的內容)。 任何人都可以在那里發現任何錯誤,我不會對此感到驚訝,因為它將與指針相關聯,這可能是花了我最多時間來理解的概念。 最初,我沒有將映射放在指針和堆上,但是將另一個變量更改為較早的變量似乎已經解決了另一個問題,因此我想嘗試一下。 可悲的是,當我也沒有將地圖放到堆上時,我遇到了幾乎相同的錯誤。

順便說一句,任何人都可以向我解釋一下堆和棧之間的區別是什么,為什么我要經歷(危險的)麻煩將變量存儲在堆中(包括指針,刪除和全部),而不是在棧上,什么時候應該使用堆,什么時候不應該使用堆。

根據您問題中的信息:

  1. DLL中的已編譯代碼似乎在其頭文件中聲明了一個MyChroma類,其中包含一堆內部類成員。

  2. 然后,您的主應用程序使用完全不同的頭文件,該頭文件定義了一個名為MyChroma的類,該類除去了其類成員。

  3. 然后,您的主應用程序根據其在頭文件中看到的內容實例化MyChroma類。

那是行不通的。 由於您的主應用程序對這些類成員一無所知,因此它實例化的實際類太小。

並實例化堆棧上的一個類。

然后,構造函數來自DLL,后者認為該類包含所有其他這些類成員。

DLL中的構造函數將嘗試對其進行初始化。

在堆棧上。

你好堆棧損壞。

答案很簡單,就是“不要做你所做的事情”。 這是未定義的行為。 您編譯的引用特定類的所有內容都必須看到該類的相同聲明(和內聯方法定義)。

句號

沒有例外。

好吧,如果有足夠的經驗,在針對特定的C ++實現時,可以安全地執行類似的操作,但實際情況並非如此。

在此之前,有一些方法可以隱藏庫提供的類的內部實現細節,但這不是您要做的。 安全的方法是使用PIMPL設計模式

您也不應做其他一些事情。 這與手頭的問題沒有直接關系,但是可以避免其他一些常見的陷阱,這些陷阱可以在沒有事先警告的情況下將地毯從腳下拉出:

  1. 不要使用use namespace std; 特別是在頭文件中。 完全忘記C ++語言中存在類似的東西。

  2. 您所有的課程也應遵循“三規則”

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM