使用静态 std::vector class 成员时发生访问冲突
Access violation when using static std::vector class member
每隔 50 次左右,我在实现 UI 的 DLL 中遇到访问冲突,大多数情况下 运行 时间都很好,我怀疑这可能是由于使用了静态向量:
这是来自 class 方法的代码快照,带有堆栈跟踪:
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
这是有问题的静态向量 declared/defined
#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 { };
这里是相关的堆栈跟踪:
Exception thrown at 0x00007FFA691212DE (vcruntime140d.dll) in
TestUI.exe: 0xC0000005: Access violation reading location
0x000001A35C589000.
vcruntime140d.dll!memcpy_repmovs() Line 114 Unknown
UI.dll!std::_Copy_memmove(unsigned short * _First, unsigned short * _Last, unsigned short * _Dest) Line 1745 C++
UI.dll!std::_Uninitialized_move>(unsigned short * const _First, unsigned short * const _Last, unsigned short * _Dest,
std::allocator & _Al) 第 1738 行 C++
UI.dll!std::vector>::_Emplace_reallocate(无符号短*
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 width, int height, HWND__ * hParent, unsigned long
dwStyle, unsigned long dwExStyle, HICON__ * hIcon, HMENU__ * hMenu)
第 68 行 C++
TestUI.exe!TestMainWindow(HINSTANCE__ * hInstance, HINSTANCE__ *
hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) 第 45 行 C++
[外码]
您是否看到此代码有任何问题,我的向量是否已正确初始化,如果是,那么为什么 push_back 失败?
你可以只使用 meyer 的单例:
而不是:
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
每隔 50 次左右,我在实现 UI 的 DLL 中遇到访问冲突,大多数情况下 运行 时间都很好,我怀疑这可能是由于使用了静态向量:
这是来自 class 方法的代码快照,带有堆栈跟踪:
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 这是有问题的静态向量 declared/defined
#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 { };
这里是相关的堆栈跟踪:
Exception thrown at 0x00007FFA691212DE (vcruntime140d.dll) in TestUI.exe: 0xC0000005: Access violation reading location 0x000001A35C589000.
vcruntime140d.dll!memcpy_repmovs() Line 114 Unknown
UI.dll!std::_Copy_memmove(unsigned short * _First, unsigned short * _Last, unsigned short * _Dest) Line 1745 C++
UI.dll!std::_Uninitialized_move>(unsigned short * const _First, unsigned short * const _Last, unsigned short * _Dest, std::allocator & _Al) 第 1738 行 C++
UI.dll!std::vector>::_Emplace_reallocate(无符号短* 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 width, int height, HWND__ * hParent, unsigned long dwStyle, unsigned long dwExStyle, HICON__ * hIcon, HMENU__ * hMenu) 第 68 行 C++
TestUI.exe!TestMainWindow(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, wchar_t * lpCmdLine, int nCmdShow) 第 45 行 C++
[外码]
您是否看到此代码有任何问题,我的向量是否已正确初始化,如果是,那么为什么 push_back 失败?
你可以只使用 meyer 的单例:
而不是:
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