将晦涩难懂的技术讲的通俗易懂
分类: LINUX
2015-01-04 23:03:13
最近在项目中使用多线程处理接收数据,运行时开始提示“数组越界”,之后有提示“内存访问冲突”,“堆损坏”。通过分析发现是多个线程同时对一个全局String变量调用append方法造成的。下面详细说一下这个问题的原因。
首先用下面简单的伪代码说明函数库中用到的String类,为了简单起见,只写出了String的关键部分,省去了原函数库中的工具函数和边界检测。
点击(此处)折叠或打开
当同时有多个线程执行可能会造成错误。首先要说的是造成错误的原因并不是append中的realloc函数,当使用多线程时会连接多线程库,而多线程库的realloc是线程安全的(内部通过加锁保证互斥).
下面分析一下造成错误的原因:
(1) 假设当前str的size为5,alloc为10;
(2) 线程1执行append,s的size为3;线程2执行append,s的size为4;
(3) 线程1执行到第16行: if( (this->size+s.size)>this->alloc),条件测试失败(因为3+5<10),此时切换到线程2执行;
(4) 线程2也执行到第16行: if( (this->size+s.size)>this->alloc),条件测试失败(因为4+5<10),然后直接向后执行memcpy(this->d+this->size,s.d,s.size);
此时size=4+5=9;
(5) 线程1向后执行memcpy(this->d+this->size,s.d,s.size),此时size=9+3=12,由于size已经大于alloc,所以数组越界造成内存错误。
其实避免这种问题的方法很简单,当多个线程访问全局变量时加锁同步就可以解决。但是我觉得还是有必要知道为什么要加锁,不加锁会造成哪些问题。