场景:
1. 有时候需要使用vector 或 map作为多线程的共享变量, map是tree结构, 读和写方法都不是线程安全的, 即同时读写会有崩溃的现象.
2. std::vector直观来说只用push_back和[] 下标访问操作应该没问题,push_back往后边加对象, 索引值只访问已经存储的变量(预先求size).注意, 这里不会删除vector元素.
可惜,这种多线程操作还是会崩溃. 单线程写和单线程读!!!
看代码:
test_vector.cpp
#include "gtest/gtest.h" #include <vector> #include <iostream> #include <Windows.h> #include "pthread.h" class A { public: A(int i):i_(i){} int i_; }; void* first = NULL; void* second = NULL; static void* Push(void* data) { std::vector<A*>& vec = *(std::vector<A*>*)data; vec.push_back(new A(-1)); first = std::addressof(vec._Myfirst); //std::cout << first << std::endl; for(int i = 0; i< 100000;++i) { vec.push_back(new A(i)); //Sleep(2); } return NULL; } static void* Read(void* data) { std::vector<A*>& vec = *(std::vector<A*>*)data; int size = vec.size(); while((size = vec.size())!= 100000) { for(int i = 0;i<size;++i) { A* a = vec[i]; second = std::addressof(vec._Myfirst); std::cout << "a->i_: " << a->i_ << std::endl; } } return NULL; } TEST(test_vector,testVector) { std::vector<A*> a; pthread_t t1; pthread_create(&t1,NULL,&Push,&a); pthread_detach(t1); pthread_t t2; pthread_create(&t2,NULL,&Read,&a); pthread_detach(t2); system("pause"); }
运行几次,偶尔就会崩溃,size一直是比实际的个数小,通过查看debug变量值,奇怪的是a的值是无效的.
内存大小很正常:
崩溃的位置: a已经是无效的数值了.
看vector代码也没看出什么问题:
void push_back(_Ty&& _Val) { // insert element at end if (_Inside(_STD addressof(_Val))) { // push back an element size_type _Idx = _STD addressof(_Val) - this->_Myfirst; if (this->_Mylast == this->_Myend) _Reserve(1); _Orphan_range(this->_Mylast, this->_Mylast); _Cons_val(this->_Alval, this->_Mylast, _STD forward<_Ty>(this->_Myfirst[_Idx])); ++this->_Mylast; } else { // push back a non-element if (this->_Mylast == this->_Myend) _Reserve(1); _Orphan_range(this->_Mylast, this->_Mylast); _Cons_val(this->_Alval, this->_Mylast, _STD forward<_Ty>(_Val)); ++this->_Mylast; } }
reference operator[](size_type _Pos) { // subscript mutable sequence #if _ITERATOR_DEBUG_LEVEL == 2 if (size() <= _Pos) { // report error _DEBUG_ERROR("vector subscript out of range"); _SCL_SECURE_OUT_OF_RANGE; } #elif _ITERATOR_DEBUG_LEVEL == 1 _SCL_SECURE_VALIDATE_RANGE(_Pos < size()); #endif /* _ITERATOR_DEBUG_LEVEL */ return (*(this->_Myfirst + _Pos)); }
目前还没找到原因,有一种可能是this->-Myfirst的值debug时没有变化,不是它的问题, 那可能就是pointer对象在改变容量时改变了对象的存储位置,时间关系没有深入研究.
环境:
visual studio c++ 2010 sp1.
作为临时解决方案, 暂时用C数组来解决这个push_back和下标访问的问题,
test_carray.cpp
#include "gtest/gtest.h" #include <vector> #include <iostream> #include <Windows.h> #include "pthread.h" class A { public: A(int i):i_(i){} int i_; }; class S { public: S() { index_ = 0; count_ = sizeof(a)/sizeof(A*); } A* a[10000]; int index_; int count_; }; static void* Push(void* data) { S* s = (S*)data; for(int i = 0; i< s->count_;++i) { s->a[i] = new A(i); s->index_ = i; //Sleep(2); } s->index_+=1; return NULL; } static void* Read(void* data) { S* s = (S*)data; int size = 0; while((size = s->index_) < s->count_) { for(int i = 0;i<size;++i) { A* a = s->a[i]; std::cout << "a->i_: " << a->i_ << std::endl; } } return NULL; } TEST(test_carray,testArray) { S s; pthread_t t1; pthread_create(&t1,NULL,&Push,&s); pthread_detach(t1); pthread_t t2; pthread_create(&t2,NULL,&Read,&s); pthread_detach(t2); pthread_t t3; pthread_create(&t3,NULL,&Read,&s); pthread_detach(t3); system("pause"); }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-14 20:55:22