2012-01-30 10 views
0

当我的应用程序试图将文本写入文件时,我正面临核心转储。它正在使用字符串操作,如代码所示。当多线程尝试调用此函数并尝试写入日志文件时,那么我的应用程序正在转储核心。我经历了不同的论坛,并尝试搜索字符串分配中的任何问题。我已经看到,我们中的一些人对该字符串赋值语句进行了评论,因为它不太好用。而是使用字符串成员函数。面向核心转储,同时将空字符串分配给字符串变量

功能:

void Debug::writeToFile() 
{ 
if(_ptrMutex == NULL) 
    _ptrMutex = new Mutex(); 
_ptrMutex->getLock(); 
write(_fd,_cacheStr.c_str(),_cacheStr.size()); 
_cacheStr = ""; //flush the write string 
_ptrMutex->releaseLock(); 
} 

cacheWriteString

bool Debug::cacheWriteString(string strIn) 
{ 
if(_ptrMutex == NULL) 
    _ptrMutex = new CndMutex(); 
_ptrMutex->getLock(); 
char timeStamp[100]; 

struct timeval tv; 
struct tm tm; 

if (gettimeofday(&tv, NULL)==0 && localtime_r((time_t*)&(tv.tv_sec), &tm)) { 
    int ret = strftime(timeStamp,sizeof(timeStamp),"%F-%T",&tm); 
    snprintf(timeStamp+ret, sizeof(timeStamp)-ret, ".%03ld", tv.tv_usec/1000); 
} else 
Time::getTimeStamp(timeStamp,100); 
_cacheStr = _cacheStr + "[" + timeStamp + "] " + strIn; 
if(_cacheStr.size() >= _maxCacheSize) 
{ 
    _ptrMutex->releaseLock(); 
    return true; 
} 
_ptrMutex->releaseLock(); 
return false; 
} 

此功能被称为

void Debug::LOG_PRINT_ERROR(char* ptrFormat,...) 
{ 
va_list argList; 
va_start(argList,ptrFormat); 

if(_logType == CONSOLE_LOG) //console log 
{ 
    cout<<"#### [ERROR] "; 
    vprintf(ptrFormat,argList); 
    cout<<endl; 
} 
else if(_logType == SYS_LOG)// [syslog] 
{ 
    syslog(LOG_ERR,"%s","[ERROR]####"); 
    vsyslog(LOG_ERR,ptrFormat,argList); 
} 
else if(_logType == FILE_LOG) 
{ 
    char str[1024]; 
    //SBYTE4 ret = vsprintf(str,ptrFormat,argList); 
    SBYTE4 ret = vsnprintf(str,1023,ptrFormat,argList); 
    str[1023]='\0'; 
    if(ret > -1) 
    { 
     string dataStr = "[ERROR]####"; 
     dataStr = dataStr +str+"\n"; 
     if(cacheWriteString(dataStr)) 
     { 
      if(chkFile() == DIM_PASS) 
      { 
       writeToFile(); 
      } 
      else 
      { 
       cout<<"#### LOG_ERROR() Unable to Write Data To File: "<<_fileName <<endl; 
      } 
     } 
    } 
    else 
    { 
     cout<<"#### LOG_ERROR() Output Error Is Encountered: "<<_fileName <<endl; 
    } 
} 
va_end(argList); 

}

核心转储详情如下:

Thread 1 (Thread 8426): 
#0 0x00a2a402 in __kernel_vsyscall() 
#1 0x0072bdf0 in raise() from /lib/libc.so.6 
#2 0x0072d701 in abort() from /lib/libc.so.6 
#3 0x0545651a in ??() from /usr/lib/libstdc++.so.6 
#4 0x05456552 in std::terminate()() from /usr/lib/libstdc++.so.6 
#5 0x0545668a in __cxa_throw() from /usr/lib/libstdc++.so.6 
#6 0x053ed1ef in std::__throw_length_error(char const*)() from /usr/lib/libstdc++.so.6 
#7 0x0543211d in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&)() from /usr/lib/libstdc++.so.6 
#8 0x05433e28 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned int, unsigned int, unsigned int)() from /usr/lib/libstdc++.so.6 
#9 0x05433fca in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace_safe(unsigned int, unsigned int, char const*, unsigned int)() from /usr/lib/libstdc++.so.6 
#10 0x05434065 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::assign(char const*, unsigned int)() from /usr/lib/libstdc++.so.6 
#11 0x0815e9a8 in Debug::writeToFile()() 
#12 0x08161866 in Debug::LOG_PRINT_ERROR(char*, ...)() 
#13 0x0812bcc6 in DimInternalMsgHandler::handlePeerStatusIndication(DimPeerStatusInd*)() 
#14 0x0812c52a in DimInternalMsgHandler::handleInternalMessage(unsigned char*, int)() 
#15 0x0812aa05 in DimDanIfController::handleInMessage(NwPacket&)() 
#16 0x081ab28f in WorkerThreadPool::onEvent(int, nxs_util::EventMessage64*)() 
#17 0x0021dd94 in nxs_util::EventHandler64::workerProc(int)() from /home/nextgen/NXS/lib/libnxsutil.so 
#18 0x001c193e in nxs_util::WorkerThread::run()() from /home/nextgen/NXS/lib/libnxsutil.so 
#19 0x001c5b36 in nxs_util::Thread::__Thread_run(void*)() from /home/nextgen/NXS/lib/libnxsutil.so 
#20 0x0087f832 in start_thread() from /lib/libpthread.so.0 
#21 0x007d4e0e in clone() from /lib/libc.so.6 

我们怀疑会=“” < _cacheStr的问题;>语句我们使用在我们的代码。我们正在考虑更改为_cacheStr.clear();但是我们现在无法再现这个核心。

如果任何人有任何想法或面临它请让我们知道。

非常感谢您的意见。

+1

小提示:创建互斥锁时,您可能在'writeToFile'中有竞争条件。如果两个线程可以进入函数并且在检查之后但在创建之前被抢占,则两个线程都可以创建互斥锁。 – 2012-01-30 09:24:05

回答

0

如果任何其他线程可以访问_cacheStr(即使只是为了检查它),而不保留_ptrMutex,这可能很容易导致这样的崩溃。

+0

其他线程必须通过这个互斥锁定机制,除非线程正在释放它。所以所有的线程都会进入正常的锁定和解锁机制。 – 2012-01-30 09:24:09

0

我看到有函数writeToFile的锁定,并且cacheStr应该是一个全局变量,但是我没有看到函数cacheWriteString,所以我认为这是一个不受保护的cacheStr变量的竞争条件在函数cacheWriteString中。 2个线程可以同时访问/修改字符串。

1

这看起来真的,真的很狡猾:

if(_ptrMutex == NULL) 
    _ptrMutex = new Mutex(); 

如果两个线程进入该块和动态地创建自己的互斥?是否有任何理由不能在初始化时创建单个互斥锁,并避免“创建互斥体”竞争条件?

+0

这是可靠的。如果没有更好的初始化位置,可以使用'pthread_do_once'正确执行此操作。 – StilesCrisis 2012-01-30 09:25:53

+0

这在初始化时间内有效,因为当两个线程在启动时间期间到来时,此点有效。但是这里应用程序不断运行,然后转储核心。因为Debug类有单个实例,所以总是最后一个互斥量将在线程中使用。我接受这个代码不应该在那里。但是在初始化时会发生崩溃。 – 2012-01-30 09:38:49

+0

@ user1177666:抱歉,如果两个线程在初始化时进入此函数,则不安全。任何事情都可能发生,比如双重解锁一个互斥体并完全破坏同步对象。这可能会导致其在随后的任何时刻出现副作用。 – 2012-01-30 09:58:27

相关问题