【发布时间】:2016-03-14 01:41:18
【问题描述】:
所以我有这个函数用于散列内部字符串,但是当我尝试运行它时,Visual Studio 2015 给了我一个调试断言失败!错误:
Program: C:\WINDOWS\SYSTEM32\MSVCP140D.dll
File: c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector
Line: 1232
Expression: vector subscript out of range
现在第一次调用 InternalString 时,我收到此错误,它在 gStringIdTable.find(sid) 行上中断。
static std::unordered_map<StringId, const char*> gStringIdTable;
StringId InternalString(const char* string) {
StringId sid = std::hash<std::string>()(string);
std::unordered_map<StringId, const char*>::iterator it = gStringIdTable.find(sid);
if (it == gStringIdTable.end()) {
gStringIdTable.insert({sid, string});
}
return sid;
}
我认为这可能是我初始化迭代器的方式有问题,所以我想试试这个:
if (gStringIdTable.find(sid) == gStringIdTable.end()) {
gStringIdTable.insert({sid, string});
}
但这给了我同样的错误。然后我想这可能与在 unordered_map 填充任何内容之前进行查找有关,所以我尝试只在函数中插入。但这也给了我同样的错误。我尝试将 const char* 转换为 std::string,然后仅在this answer's 建议处处理 unordered_map 中的字符串,但得到了同样的错误。我尝试使用 emplace 代替 insert,尝试使用 std::make_pair,但所有组合均无济于事。
现在,我是否遗漏了一些明显错误的东西,或者某处有错误?
更新
好的,这是一个编译版本,但我仍然得到错误。我在 Visual Studio 2015 中启动了一个空的 c++ 项目,并添加了这 3 个文件以匹配它当前在我的项目中的实现方式:
main.cc
#include "stringid.h"
const static mynamespace::StringId kSidOne = mynamespace::InternalString("One");
int main(int argc, char *argv[]) {
return 0;
}
stringid.cc
#include "stringid.h"
#include <string>
#include <unordered_map>
namespace mynamespace {
static std::unordered_map<StringId, std::string*> gStringIdTable;
StringId InternalString(const char* string) {
StringId sid = std::hash<std::string>()(string);
if (gStringIdTable.find(sid) == gStringIdTable.end()) {
gStringIdTable.emplace(sid, new std::string(string));
}
return sid;
}
} // mynamespace
字符串.h
#ifndef STRINGID_H_
#define STRINGID_H_
namespace mynamespace {
typedef unsigned int StringId;
StringId InternalString(const char* string);
} // mynamespace
#endif // STRINGID_H_
我还对函数进行了一些调试,看看我是否能找出问题出在哪里,看起来当 find 函数抓取相关存储桶时,它返回 null 或 0,然后 _Begin 函数抛出错误,因为大小等于零。
小更新
我也试过用 gcc 编译。它编译得很好,但我仍然在 find() 上遇到错误。
【问题讨论】:
-
我试图重现该问题但失败了。它对我来说运行得很好。请提供一个mcve 而不是几个sn-ps。
-
听起来像静态初始化命令惨败。特别是,
gStringIdTable不能保证在调用InternalString以初始化kSidOne时被正确初始化。 -
@T.C.哦耶!!我什至不认为这可能是一个问题!这是我的第一个严肃的 C++ 项目,所以我相信我将来还会遇到更多这样的问题。谢谢你的帮助!!
标签: c++ c++11 std unordered-map