提问人:Alessandro Savona 提问时间:7/11/2023 最后编辑:Remy LebeauAlessandro Savona 更新时间:7/12/2023 访问量:102
将 void* 转换为 (vector<void*>*) 时出现问题
problem casting a void* to a (vector<void*>*)
问:
我目前正在研究一个复杂的逻辑,其中我有一个具有这些值:map<string,void*>
string mystring[10] = {"key1","key2","keyN"};
for(string s: mystrings){
vector<void*> v;
v.push_back(this);
v.push_back(&s);
map.insert({s,&v});
}
在某个时刻,我必须将我的传递给触发回调的计时器:vector
mytimer(int milliseconds, mycallback,void* (parameter of the callback));
this->mytimer(1000,MY_CALLBACK,map.at("Key1"));
问题出在回调中:
static void MY_CALLBACK(void*);
void MY_CALLBACK(void* args){
auto obj = (vector<void*>*) args;
auto key = (string*) obj->at(1);
auto logic = (MY_CLASS *) obj->at(0);
some logic;
}
程序崩溃,因为当我尝试获取 的任何值时出现“超出范围”错误。vector
问题是什么?
答:
4赞
463035818_is_not_an_ai
7/11/2023
#1
这里
for(string s: mystrings){ vector<void*> v; v.push_back(this); v.push_back(&s); map.insert({s,&v}); }
您正在插入指向一个向量的指针,该向量的生存期在迭代结束时结束。地图中的指针是无用的。这是一个悬而未决的指针。稍后取消引用指针会导致未定义的行为。
1赞
Remy Lebeau
7/12/2023
#2
您存储的是指针指向在有机会使用指针之前被销毁的对象。
您的循环正在迭代数组,将指向每个数组副本的指针推送到 .副本在当前小版本结束时被销毁。而且,它本身是每次迭代的本地函数,因此在将指向它的指针推入 .for
string[]
string
vector
vector
map
对于您正在尝试的内容,请尝试更多类似的东西:
using var = std::variant<MY_CLASS*, std::string>;
using vec = std::vector<var>;
...
std::map<std::string, vec> my_map;
...
std::string mystring[10] = {"key1", "key2", "keyN"};
for(auto& s: mystrings){
vec v;
v.emplace_back(this);
v.emplace_back(s);
my_map.insert({s, std::move(v)});
}
...
this->mytimer(1000, MY_CALLBACK, &(my_map.at("key1")));
...
void MY_CALLBACK(void* args){
auto v = static_cast<vec*>(args);
auto logic = std::get<MY_CLASS*>(v->at(0));
auto key = std::get<std::string>(v->at(1));
// use logic and key as needed...
}
请注意,这假定您在计时器运行时没有修改 的内容。如果这样做,则需要动态创建,例如:map
vector
using var = std::variant<MY_CLASS*, std::string>;
using vec = std::vector<var>;
...
std::map<std::string, std::unique_ptr<vec>> my_map;
...
std::string mystring[10] = {"key1", "key2", "keyN"};
for(auto& s: mystrings){
auto v = std::make_unique<vec>();
v->emplace_back(this);
v->emplace_back(s);
my_map.insert({s, std::move(v)});
}
...
this->mytimer(1000, MY_CALLBACK, my_map.at("key1").get());
...
void MY_CALLBACK(void* args){
auto v = static_cast<vec*>(args);
auto logic = std::get<MY_CLASS*>(v->at(0));
auto key = std::get<std::string>(v->at(1));
// use logic and key as needed...
}
评论
v.push_back(&s);
-- 您正在添加指向临时变量的指针。您认为每次循环迭代时该变量会发生什么?map.insert({s,&v});
将局部变量的地址(添加到映射中)添加,然后该变量超出范围,留下一个悬空的指针。v
MY_CALLBACK