簡體   English   中英

c++ std::unordered_map singleton 訪問沖突錯誤

[英]c++ std::unordered_map singleton access violation error

template <typename T> class singleton
{
public:
    static T* ms_singleton;

    singleton()
    {
        assert(!ms_singleton);
        long offset = (long)(T*)1 - (long)(singleton <T>*) (T*) 1;
        ms_singleton = (T*)((long)this + offset);
    }

    virtual ~singleton()
    {
        assert(ms_singleton);
        ms_singleton = 0;
    }

    static T& Instance()
    {
        assert(ms_singleton);
        return (*ms_singleton);
    }

    static T* instance_ptr()
    {
        return (ms_singleton);
    }
};

class Test
{
private:
   DWORD X;
}

typedef Test* LPTEST;

class TestManager : public singleton<TestManager>
{
public:
    TestManager();
    virtual ~TestManager();

    LPTEST  CreateTest(DWORD id);

protected:

private:
    std::unordered_map<DWORD, LPTEST> test_map;
};

LPTEST TestManager::CreateTest(DWORD id)
{
    LPTEST test = new Test;

    if (id)
    {
        test_map.insert(std::make_pair(id, test));
    }

    return (test);
}

我創建了一個類似的代碼。

當我運行以下 function 時。

LPTEST 測試 = TestManager::Instance().CreateTest(61);

但“test_map.insert”給出了訪問沖突錯誤。

test_map.insert -> 如果我關閉 function 它工作正常。

所有代碼都正常。 為什么我對 std:map 之類的代碼有這樣的問題。

如果你能幫忙,我會很高興。

通過如下更改 Singleton 代碼。 我解決了這個問題。

template <typename T> class singleton
{
public:
    singleton() {}
    ~singleton() {}

    static T& Instance()
    {
        static T instance;
        return instance;
    }

    singleton(const singleton&) = delete;
    singleton& operator=(const singleton&) = delete;
};

@drescherjm,@UnholySheep 感謝您的幫助。

是不是覺得這段代碼中有一段代碼會在以后造成麻煩? 這段代碼可以更好嗎? 如何?

您的代碼太復雜、危險並且充滿了未定義的行為

以下是一些問題:

  • 整個offset計算完全沒有意義!
  • 應避免 C 樣式鑄造。 您應該始終使用 C++ 轉換,如static_castdynamic_cast完全理解為什么使用這種轉換。
  • 您有一個指向 T 的指針,但您從未為此類 object 分配任何 memory。 如所寫,您大多假設 memory 在那里。

在實踐中,使用 Meyer 的 singleton,您很少需要定義這樣的模板。

這樣的事情要簡單得多:

using TestMap = std::unordered_map<DWORD, Test>;

class TestManager
{
public:

    static TestMap &GetTestMap();

    Test *CreateTest(DWORD id);
};

// testmanager.cpp
TestMap &TestManager::GetTestMap()
{
    // Creation of the object is thread safe but if you want
    // to use it from multiple threads, you have to provide
    // your own synchronisation like mutex.
    static TestMap testMap;
    return testMap;
}

Test *TestManager::CreateTest(DWORD id)
{
    // allocate a pair and return a reference to value
    // if key already exist, return a reference to existing value.
    auto &mapValue = GetTestMap()[id];

    // as unique_ptr are stored in the map, 
    // memory managment can be simplified
    // could also use make_unique here
    mapValue.reset(new Test);

    // return a raw pointer as in your original code
    return mapValue.get();
}

根據需要和您對 C++ 的理解程度,該代碼可以改進...正如所寫,一旦您了解一些基本的 C++ 11,就很容易理解。

暫無
暫無

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

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