fengyue

CString不是线程安全的

我们用MFC开发时经常会用到CString类,无可否认,CString类是很好用,但很少人注意到CString类不是线程安全的。一般地,界面编程都是在主线程,很少用到多线程,所以不会遇到什么问题。但是,当我们多个线程同时操作同一个CString类型变量时,就可能会出现内存地址错误,最终导致进程异常退出。内存错误导致的问题也很难调查,通常导致内存错误的地方没有马上报异常,而且在程序的其他地方才捕获异常。
CString类的Debug版本和Release版本不完全一样,Debug版本则直接分配(MFC在Debug版本有内存管理,主要是为了排错,内存泄漏等),CString类在Release版本会使用定长内存管理(CFixedAlloc类),主要管理是4个长度的内存,如下:
1AFX_STATIC CFixedAlloc _afxAlloc64(ROUND4(65*sizeof(TCHAR)+sizeof(CStringData)));
2AFX_STATIC CFixedAlloc _afxAlloc128(ROUND4(129*sizeof(TCHAR)+sizeof(CStringData)));
3AFX_STATIC CFixedAlloc _afxAlloc256(ROUND4(257*sizeof(TCHAR)+sizeof(CStringData)));
4AFX_STATIC CFixedAlloc _afxAlloc512(ROUND4(513*sizeof(TCHAR)+sizeof(CStringData)));
这样做应该是防止内存碎片和提高效率,由于CString类都会重用分配的定长内存,所以一般异常的地方大多数也是在CString操作的地方。有兴趣可以看看CString类的实现。
避免这样的问题最简单的办法就是加锁或者不用CString类。加锁用临界区就可以,实现比较简单,在这里不多说。

posted on 2011-11-24 10:58 风悦 阅读(2889) 评论(5)  编辑 收藏 引用 所属分类: C/C++

Feedback

# re: CString不是线程安全的 2011-11-24 11:37 陈梓瀚(vczh)

用std::wstring  回复  更多评论   

# re: CString不是线程安全的 2011-11-24 11:51 mtian

MFC,STL这种类库一般都不是线程安全的,毕竟内部加锁是会降低效率的  回复  更多评论   

# re: CString不是线程安全的[未登录] 2011-11-24 11:59 陈梓瀚(vczh)

@mtian
但是cout是线程安全的——不过如果非要用一个线程安全的string,就得学C#,它的string是生成后不可修改的。哪怕是你insert,都会搞出一个新string。不过因为有CLR的关系,这个效率比C++的那种传统模式还要好。  回复  更多评论   

# re: CString不是线程安全的 2011-11-26 23:59 Benjamin

http://msdn.microsoft.com/zh-cn/library/cc438572(v=VS.71).aspx,MSDN很早都有说明:“对于大量使用字符串的代码(或多线程代码),默认的内存管理器可能就无法理想地工作。”  回复  更多评论   

# re: CString不是线程安全的 2011-11-29 22:37 王继

std::wstring一样线程不安全,更郁闷的是VS自带的WTL,居然不能在dll函数参数中传来传去,否则内存泄露.boost可以的.  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理