Нарушение прав доступа при использовании статического члена класса std :: vector - PullRequest
0 голосов
/ 20 октября 2019

Каждые 50-е или около того времени, когда я получал нарушение прав доступа в своем интерфейсе, реализующем DLL, в основном время выполнения просто отлично, я подозреваю, что это может быть связано с использованием статического вектора:

Вот снимок кода из методов классас трассировкой стека:

BaseWindow.hpp

#define UI_API __declspec(dllexport)

class UI_API BaseWindow
    : public Object // base class for ref counting
{
     // the rest of the code...

protected:

    /** Register window class */
    [[nodiscard]] virtual bool RegisterCls(const WNDCLASSEX& wnd_class) const;

    /** fill in window class info struct */
    [[nodiscard]] virtual bool GetClsInfo(const PCTSTR& class_name, WNDCLASSEX& wnd_class) const;

     // the rest of the code...

};

BaseWindow.cpp

bool BaseWindow::GetClsInfo(const PCTSTR& class_name, WNDCLASSEX& wnd_class) const
{
    if (mhInstance) // handle to HINSTANCE
    {
        if (GetClassInfoEx(mhInstance, class_name, &wnd_class))
            return true;
        else return false;  // class does not exist, not an error

    }
    else // error handling
    {
        ShowError(Exception(GenericErrorCode::InvalidHandle, TEXT("Hinstance should not be nullptr")), ERR_BOILER);
        return false;
    }
}

bool BaseWindow::RegisterCls(const WNDCLASSEX& wnd_class) const
{
    WNDCLASSEX wcex{};

    // If the function does not find a matching class and successfully copy the data,
    // the return value is zero.
    if (!GetClsInfo(wnd_class.lpszClassName, wcex)) // calls above function!
    {
        // If the function fails, the return value is zero. 
        const ATOM atom = RegisterClassEx(&wnd_class);

        if (!atom) // error handling
        {
            ShowError(ERR_BOILER);
            return false;
        }
        else
        {
            ClassAtoms::AddClassAtom(atom); // call below function!
        }
    }

    return true;
}

ClassAtoms.hpp Это где проблемный статический вектор объявлен / определен

#define SUPPRESS(...) __pragma(warning(suppress : __VA_ARGS__))

class UI_API ClassAtoms
{   
     // the rest of the code...

public:
    /** Add registered window class to ATOM container */
    inline static void AddClassAtom(const ATOM& atom);

    // the rest of the class

private:
    /** Container for registered window classes */
    SUPPRESS(4251);  // needs to have dll-interface (inlining will result in internal compiler error)
    static std::vector<ATOM> mAtoms;

      // the rest of the code...
};

void ClassAtoms::AddClassAtom(const ATOM& atom)
{
    mAtoms.push_back(atom);
}

ClassAtoms.cpp

SUPPRESS(26426);  // Global initializer calls a non-constexpr function
std::vector<ATOM> ClassAtoms::mAtoms { };

А вот соответствующая трассировка стека:

Исключение, выданное в 0x00007FFA691212DE (vcruntime140d.dll) в TestUI.exe: 0xC0000005: Место чтения нарушения доступа 0x000001A35C589000.

vcruntime140d.dll! 1031 *

UI.dll! Std :: _ Copy_memmove (неподписанный короткий * _Первый, неподписанный короткий * _Last, неподписанный короткий * _Dest) Строка 1745 C ++

UI.dll! Std :: _ Uninitialized_move>(unsigned short * const _First, unsigned short * const _Last, unsignedshort * _Dest, std :: allocator & _Al) Строка 1738 C ++

UI.dll! std :: vector> :: _ Emplace_reallocate (unsigned short * const _Whereptr, const unsigned short & <_Val_0>) Строка 707 C ++

UI.dll! Std :: vector> :: emplace_back (const unsigned short & <_Val_0>) Строка 659 C ++

UI.dll! Wsl :: ui :: BaseWindow :: RegisterCls(const tagWNDCLASSEXW & wnd_class) Строка 131 C ++

UI.dll! wsl :: ui :: MainWindow :: Initialize (HINSTANCE__ * hInstance, int x, int y, ширина int, высота int, HWND__ * hParent,unsigned long dwStyle, unsigned long dwExStyle, HICON__ * hIcon, HMENU__ * hMenu) Строка 68 C ++

TestUI.exe! TestMainWindow (HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpm C ++ C ++ CmD)1046 *

[Внешний код]

Видите ли вы какие-либо проблемы с этим кодом, правильно ли инициализирован мой вектор, если да, то почему происходит сбой push_back?

1 Ответ

1 голос
/ 20 октября 2019

Вы можете просто использовать синглтон Мейера:

вместо:

static std::vector<ATOM> mAtoms;

сделать функцию:

static auto& atoms() {
  static std::vector<ATOM> s;
  return s;
}

Теперь вектор инициализируется при первом использовании,Это также влияет на статический порядок уничтожения - что может или не может быть проблемой - , но вы должны знать об этом .


В качестве альтернативы вы можете попробоватьвстроенная инициализация - это может переместить init. в иници. закажите.

 static inline std::vector<ATOM> mAtoms;

и удалите .cpp init.


При этом, очень вероятно, что это не этот вектор, вызывающий повреждение кучи .

Вам необходимо отладить повреждения кучи. На Windows хорошее начало _CrtSetDbgFlag

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...