码迷,mamicode.com
首页 > 编程语言 > 详细

[C/C++标准库]_[初级]_[std::vector的多线程读写问题]

时间:2015-08-07 19:49:24      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:c++   vector   崩溃   push_back   多线程   


场景:

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");
}




版权声明:本文为博主原创文章,未经博主允许不得转载。

[C/C++标准库]_[初级]_[std::vector的多线程读写问题]

标签:c++   vector   崩溃   push_back   多线程   

原文地址:http://blog.csdn.net/infoworld/article/details/47343347

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!