C++ - unordered_map 结构内存问题
C++ - unordered_map memory issues with struct
我今天决定将我的代码从 vector
更改为 unordered_map
,这样我就可以拥有字符串键值。但是,unordered_map
似乎不太有效。
所以基本上我有一个结构类型:
typedef struct WindowData //the infamous Window Data struct
{
HWND handle;
std::unordered_map<std::string, WindowData*> children;
COLORREF color;
int height;
int width;
int x;
int y;
WindowData *parent;
bool visible;
} windowData;
然后是它的全局定义实例:
WindowData MainWData = {NULL, std::unordered_map<std::string, WindowData*>(), NULL, 0, 0, 0, 0, NULL, true};
然后函数添加一个元素到unordered_list
(结构成员children
):
void GUI::CreateTitle(WindowData *data) //Home/About page title
{
/*...*/
WindowData wd={handle, std::unordered_map<std::string, WindowData*>(), ColorPalette.BackgroundColor, Nheight, Nwidth, x, y, data, true}; //all these values are defined within the scope of this function except ColorPalette, which is global
data->children.insert(std::make_pair("title", &wd));
}
最后,我还有其他几个函数,包括 GUI class 的成员和非成员,它们读取地图元素,例如这个:
void GUI::CreateAboutButton(WindowData *data) //Home Page About Button
{
/*...*/
int y=data->children.at("title")->y + data->children.at("title")->height + 100;
/*...*/
}
现在,来描述错误。从 GUI::CreateAboutButton()
函数中获取 int y
。每次程序 运行 时,该值都应该相同。通常,它是 219 之类的东西。但是,现在,每次程序 运行 时它都会改变。有时 y
是正确的值。其他时候它是 0。其他时候它大于 40 000。
我知道这是一个内存问题,因为有时当程序 运行 时,它会立即发出段错误信号,而如果不是,Dr. Memory 会显示两打 "Uninitialized Read" 错误.我的猜测是,因为 unordered_map 值必须是指向结构的指针(如果它只是结构值而不是指针,程序将无法编译),一旦结构实例 wd
来自GUI::CreateTitle()
超出范围,地图仍然指向其旧内存位置而不是实际实例。但是我不知道该怎么做(这是我第一次实现 unordered_map
)来解决这个问题。我尝试将 unordered_map::insert
换成 unordered_map::emplace
,但这始终导致段错误。
感谢任何帮助。
编辑:下面评论中的诊断/解决方案引导我通过将 wd
定义为 class 的 public 成员来解决问题。现在工作正常,所有内存错误都已解决。
问题在于在映射中存储指向局部变量 wd
的指针。局部变量在 CreateTitle
结束时被销毁,映射中的指针变为悬空。一种可能的解决方案是让地图拥有 children WindowData
,例如使用 unique_ptr
:
std::unordered_map<std::string, std::unique_ptr<WindowData>> children;
然后就地创建:
void GUI::CreateTitle(WindowData *data)
{
/*...*/
data->children.emplace(
"title",
make_unique<WindowData>(handle, std::unordered_map<std::string, std::unique_ptr<WindowData>>(), ColorPalette.BackgroundColor, Nheight, Nwidth, x, y, data, true)
);
}
添加编辑:将 wd
定义为 WindowData
的 public 成员只有在只有一个 child 时才有效。但是,那样的话,拥有地图就没有意义了,对吗?
我今天决定将我的代码从 vector
更改为 unordered_map
,这样我就可以拥有字符串键值。但是,unordered_map
似乎不太有效。
所以基本上我有一个结构类型:
typedef struct WindowData //the infamous Window Data struct
{
HWND handle;
std::unordered_map<std::string, WindowData*> children;
COLORREF color;
int height;
int width;
int x;
int y;
WindowData *parent;
bool visible;
} windowData;
然后是它的全局定义实例:
WindowData MainWData = {NULL, std::unordered_map<std::string, WindowData*>(), NULL, 0, 0, 0, 0, NULL, true};
然后函数添加一个元素到unordered_list
(结构成员children
):
void GUI::CreateTitle(WindowData *data) //Home/About page title
{
/*...*/
WindowData wd={handle, std::unordered_map<std::string, WindowData*>(), ColorPalette.BackgroundColor, Nheight, Nwidth, x, y, data, true}; //all these values are defined within the scope of this function except ColorPalette, which is global
data->children.insert(std::make_pair("title", &wd));
}
最后,我还有其他几个函数,包括 GUI class 的成员和非成员,它们读取地图元素,例如这个:
void GUI::CreateAboutButton(WindowData *data) //Home Page About Button
{
/*...*/
int y=data->children.at("title")->y + data->children.at("title")->height + 100;
/*...*/
}
现在,来描述错误。从 GUI::CreateAboutButton()
函数中获取 int y
。每次程序 运行 时,该值都应该相同。通常,它是 219 之类的东西。但是,现在,每次程序 运行 时它都会改变。有时 y
是正确的值。其他时候它是 0。其他时候它大于 40 000。
我知道这是一个内存问题,因为有时当程序 运行 时,它会立即发出段错误信号,而如果不是,Dr. Memory 会显示两打 "Uninitialized Read" 错误.我的猜测是,因为 unordered_map 值必须是指向结构的指针(如果它只是结构值而不是指针,程序将无法编译),一旦结构实例 wd
来自GUI::CreateTitle()
超出范围,地图仍然指向其旧内存位置而不是实际实例。但是我不知道该怎么做(这是我第一次实现 unordered_map
)来解决这个问题。我尝试将 unordered_map::insert
换成 unordered_map::emplace
,但这始终导致段错误。
感谢任何帮助。
编辑:下面评论中的诊断/解决方案引导我通过将 wd
定义为 class 的 public 成员来解决问题。现在工作正常,所有内存错误都已解决。
问题在于在映射中存储指向局部变量 wd
的指针。局部变量在 CreateTitle
结束时被销毁,映射中的指针变为悬空。一种可能的解决方案是让地图拥有 children WindowData
,例如使用 unique_ptr
:
std::unordered_map<std::string, std::unique_ptr<WindowData>> children;
然后就地创建:
void GUI::CreateTitle(WindowData *data)
{
/*...*/
data->children.emplace(
"title",
make_unique<WindowData>(handle, std::unordered_map<std::string, std::unique_ptr<WindowData>>(), ColorPalette.BackgroundColor, Nheight, Nwidth, x, y, data, true)
);
}
添加编辑:将 wd
定义为 WindowData
的 public 成员只有在只有一个 child 时才有效。但是,那样的话,拥有地图就没有意义了,对吗?