将void*转为vector<void*>*后程序触发越界崩溃,求问题原因
问题分析:vector访问越界崩溃原因
问题代码回顾
数据存储代码
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}); }
定时器与回调代码
// 定时器调用 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<void*> v是循环体内的局部变量,每次循环迭代结束后,这个vector的生命周期就会终止,对应的栈内存会被系统回收或标记为可复用。你将&v插入map,本质是存储了一个野指针。
当定时器触发回调时,通过map.at("Key1")拿到的指针指向的内存已经完全失效——既不是原来的vector结构,内存内容也可能被其他数据覆盖。此时调用obj->at(0)或obj->at(1),访问的是无效内存,直接触发"out of range"错误(甚至会出现更严重的未定义行为)。
另外还有一个隐藏问题:循环中的string s同样是局部变量,你把&s存入vector,后续访问该指针时,对应的string对象也早已被销毁,同样会引发问题。
解决思路
- 避免存储局部变量指针:改用动态分配内存(如
new vector<void*>),或使用智能指针(如std::shared_ptr<std::vector<void*>>)管理对象生命周期,确保回调触发时,vector的内存仍有效。 - 处理string指针问题:不要存储局部string的指针,改为存储string的副本,或动态分配string对象。
修改示例
string mystring[10] = {"key1","key2","keyN"}; for(const string& s: mystring){ // 动态分配vector,延长生命周期 auto v = new vector<void*>(); v->push_back(this); // 动态分配string,存储副本避免局部变量销毁问题 v->push_back(new string(s)); map.insert({s, v}); }
注意:使用动态分配后,需在回调完成或不再需要时手动释放内存,避免泄漏;使用智能指针可自动管理内存,更安全。
内容的提问来源于stack exchange,提问作者Alessandro Savona
相关产品推荐
相关产品推荐

