【发布时间】:2020-10-26 22:47:34
【问题描述】:
您好,我有一个在 Fedora25 上运行的跨平台 C++ 应用程序,它在执行大约一天后会崩溃,并出现错误 realloc(): invalid next size。
我已将问题缩小到特定 pthread 上,该 pthread 定期向连接的客户端发送更新并清空传出消息队列。我在线程调用的函数内部为 char * 分配空间,我在发送后释放了空间。我通常不使用 C++,所以我在后台做 std::string 的东西,然后在需要时转换为 char *。我想确保我没有遗漏一些简单的东西以及有关如何重组或解决此问题的任何提示。
static void* MyPThreadFunc(void * params) {
assert(params);
MyAppServer *pAppServer = (MyAppServer *)params;
if(pAppServer != NULL) {
int loopCounter = 1;
char* tempBuf;
int tempBufLen;
int tempDatSetDelay;
while(true) {
for(int i=0; i<pAppServer->GetUpdateDataSetCount();i++) {
tempDatSetDelay = pAppServer->GetDataSetDelay(pAppServer->VecDatSets[i].name);
if(tempDataSetDelay == 1 ||(tempDataSetDelay > 0 && loopCounter % tempDataSetDelay == 0)) {
pAppServer->UpdateDataSetMsgStr(pAppServer->VecDataSets[i]);
tempBuf = (char*)pAppServer->GetDataSetMsgStr(i); //returns const char*
broadcast(pAppServer->Con,mg_mk_str(tempBuf));
delete [] tempBuf;
}//if
} //for
//empty outgoing queue
tempBuf = pAppServer->OUtgoingMsgQueue.peek(tempMsgLen);
while(tempMsgLen>0) {
broadcast(pAppServer->Con,mg_mk_str(tempBuf));
pAppServer->OUtgoingMsgQueue.dequeue();
delete [] tempBuf;
tempBuf = pAppServer->OUtgoingMsgQueue.peek(tempMsgLen);
}
sleep(1);
loopCounter = loopCounter==std::numeric_limits<int>::max() ? 1 : ++loopCounter;
} //while
pAppServer=0;
}
}
const char* AppServer::GetDataSetMsgStr(const int idx) {
pthread_mutex_lock(&mLock);
// Dynamically allocate memory for the returned string
char* ptr = new char[VecDataSets[idx].curUpdateMsg.size() + 1]; // +1 for terminating NUL
// Copy source string in dynamically allocated string buffer
strcpy(ptr, VecDataSets[idx].curUpdateMsg.c_str());
pthread_mutex_unlock(&mLock);
// Return the pointer to the dynamically allocated buffer
return ptr;
}
char* MsgQueue::peek(int &len) {
char* myBuffer = new char[512];
len = 0;
pthread_mutex_lock(&mLock);
if(front==NULL) {
len = -1;
pthread_mutex_unlock(&mLock);
return myBuffer;
}
len = front->len;
strncpy(myBuffer,front->chars,len);
pthread_mutex_unlock(&mLock);
return myBuffer;
}
【问题讨论】:
-
我认为您不应该使用任何
new[]或delete[]调用,而应在整个代码中使用std::string。仅在函数需要时才使用const char *,这可以通过使用c_str()成员函数轻松实现。你也有这个:tempBuf = pAppServer->OUtgoingMsgQueue.peek(tempMsgLen);,并且没有迹象表明该函数是否使用new[]来分配内存(你稍后调用delete [] tempBuf)。 -
嗨@PaulMcKenzie 感谢您的意见。实际上,我在代码 sn-p 的底部使用 peek() 函数。
-
在 MsgQueue::peek() 中,如果
front->len > 511会发生什么? -
@user3583535 在
peek中,您过早地分配内存,甚至不知道是否有必要这样做。然后你假设它只分配了 512 个字节,但情况可能并非如此(正如前面的 cmets 所指出的那样),最后,分配不受互斥体保护,因此不是线程安全的。 -
这对 peek(() 有用吗?char* MsgQueue::peek(int &len) { pthread_mutex_lock(&mLock); len = 0; if(front==NULL) { len = -1; char* emptyBuffer = new char[1]; pthread_mutex_unlock(&mLock); return emptyBuffer; } len = front->len; char* myBuffer = new char[len+1]; strncpy(myBuffer,front->chars,len); pthread_mutex_unlock(&mLock); return myBuffer; }
标签: c++ heap-corruption char-pointer