C++ 将空字符串分配给字符串变量时面临核心转储

C++ 将空字符串分配给字符串变量时面临核心转储,c++,C++,当我的应用程序试图将文本写入文件时,我面临核心转储。它使用字符串操作,如代码所示。当多线程尝试调用此函数并尝试写入日志文件时,我的应用程序正在转储内核。我已经通过不同的论坛,并试图搜索字符串分配中的任何问题。我看到我们中的一些人对字符串赋值语句进行了评论,因为它不适合使用。而是使用字符串成员函数 功能: void Debug::writeToFile() { if(_ptrMutex == NULL) _ptrMutex = new Mutex(); _ptrMutex->getL

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

功能:

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();
}
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
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);
void Debug::LOG\u PRINT\u错误(char*ptrFormat,…)
{
va_列表argList;
va_启动(argList,ptrFormat);
if(\u logType==CONSOLE\u LOG)//控制台日志
{

cout如果任何其他线程可以访问cacheStr
(即使只是为了检查它)虽然未保持
\u ptrMutex
,但这很容易导致这样的崩溃。

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

这看起来非常非常危险:

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

如果两个线程进入这个块并动态创建它们自己的互斥锁呢?是否有任何原因导致您不能在初始化时创建单个互斥锁并避免“创建互斥锁”竞态条件?

一个小提示:在创建互斥体时,
writeToFile
中可能存在竞态条件。如果两个线程可以进入函数,并且一个线程在检查后但在创建之前被抢占,那么两个线程都可以创建互斥体。除非线程工作,否则其他线程必须通过此互斥锁机制ing on会释放它。因此所有线程都将进入正常的锁定和解锁机制。这是不可靠的。如果没有更好的初始化位置,您可以使用
pthread_do_once
来正确地执行此操作。这在初始化时是有效的,因为当两个线程在初始化时,这一点是有效的。但是这里应用程序正在连续运行,然后转储内核。因为调试类只有一个实例,所以始终会在线程之间使用最后一个互斥体。我同意此代码不应该存在。但在初始化时会发生崩溃。@user1177666:很抱歉,如果在初始化时有两个线程进入此函数,这是不安全的我。任何事情都可能发生,例如双重解锁一个互斥锁和完全破坏同步对象。这可能会在以后的任何时间点造成破坏性的副作用。非常感谢您的输入。我考虑到这一点。但目前发生的任何核心转储都不是因为这个问题,我支持e、 你怎么想?@user1177666:除非你解决了这个问题,否则你永远都不会知道。从表面上看
\u cacheStr=“”
除非对象已损坏或执行了一些线程不安全的操作,否则不应失败。鉴于此,您确实需要修复发现的所有潜在线程错误。我看不到任何具体证据表明此错误不是崩溃的根本原因。