王骏的博客
编程、网络技术点滴...

公告

逐渐将VC知识库的博客迁移到这里!

随笔分类

随笔档案

相册

最新评论

阅读排行榜

评论排行榜

程序员博客   首页  新随笔  订阅  管理  登录 
 
王骏的博客 阅读(1955) 评论(20)
问题由来: 一个多线程程序运行一段时间后变得不正常,许多string类型变量的内容不正常。
因为程序在本机运行一直正常,而拿到一台服务器上运行有问题,怀疑服务器上是多CPU具有
真正的并发性造成某个未同步的变量操作异常。检查所有应该同步的代码,似乎都进行了正确的同步。
大致代码如下:

#include "stdafx.h"
#include 
<process.h>
#include 
<iostream>
#include 
<conio.h>
#include 
<string>

string                g_str;
CRITICAL_SECTION    g_cs;

void LockString() { EnterCriticalSection(&g_cs); };
void UnlockString() { LeaveCriticalSection(&g_cs); };

void SetString(char * szText)
{
    LockString();

    g_str 
= szText;

    UnlockString();
}


string GetString()
{
    
string strResult;

    LockString();

    strResult 
= g_str;

    UnlockString();

    
return strResult;
}


UINT ThreadProc(LPVOID lpParam)
{
    
// 为了使现象明显,这里进行了大量循环
    for(int i = 0; i < 200000; i++)
    
{
        
string strTmp = GetString();
    }


    
return 0;
}


#define        MAX_THREADS        200

int main(void)
{
    ::InitializeCriticalSection(
&g_cs);

    SetString(
"VC知识库");

    HANDLE hThreads[MAX_THREADS];

    UINT nThreadID;
    
int i;

    
// 开启线程
    for(i = 0; i < MAX_THREADS; i++)
        hThreads[i] 
= (HANDLE)_beginthreadex(NULL, 0, (unsigned (__stdcall *)(void *))ThreadProc, NULL, 0&nThreadID);

    
// 等待线程结束
    for(i = 0; i < MAX_THREADS; i++)
        ::WaitForSingleObject(hThreads[i], INFINITE);
    
    
// 输出结果
    cout << "string:" << GetString() << endl;

    ::DeleteCriticalSection(
&g_cs);

    getch();
    
return 0;
}


代码中唯一共用的变量g_str已经用临界区进行了同步,似乎没有问题了。但运行的时候却发现有时没有运行到cout时程序便异常退出,
或cout并没有输出正确的字符串。

经过调试最后发现问题是出在 string strTmp = GetString();
因为VC6自带的STL中的string采用cow方式,这种字符串的浅拷贝带来了多线程时的安全问题。而且这种错误隐藏得比较深,很难调试排错。

结论:如果要在多线程程序中进行string变量的传递,建议使用深拷贝的string类,听说stlport没问题(本人没有测试过),如果采用VC.NET, 其自带的string是安全的。

测试环境:双Intel Xeon CPU 2.8G, WIN2003, VC6, VC.NET