Pointer variable assignment has copied partial memory when using multithread - c++

I'm trying to make multithread c++ program.
I've been testing my program for long time, and sometimes got SIGSEGV (segmentation fault).
And I found a pointer variable copied partial memory only, not all.
Here is parts of my code.
Class definition
class Message
{
public:
Message() {}
virtual ~Message() {}
virtual void execute() = 0; //do something...
}
class Job
{
public:
Job();
~Job();
void post(Message *message);
void execute(Message *message);
private:
Message *_queue[1024] = {nullptr,};
volatile int _head = 0;
int _tail = 0;
};
And 4 of threads were running and call method of same Job class instance.
Thread 1 call this method.
void Job::execute(Message *message)
{
if (message != nullptr)
{
int index = __sync_fetch_and_add(&_head, 1) % 1024;
_queue[index] = message;
}
while (_tail != _head)
{
int index = _tail % 1024;
Message *workingMessage = _queue[index];
while (workingMessage == nullptr)
{
sched_yield();
workingMessage = _queue[index];
}
workingMessage->execute();
_queue[index] = nullptr;
++_tail; //this is changed on Thread 1 only!
}
}
Thread 2~4 call this method.
void Job::post(Message *message)
{
int index = __sync_fetch_and_add(&_head, 1) % 1024;
_queue[index] = message;
}
After several minutes, I've got SIGSEGV crash on this part of Thread 1.
workingMessage->execute(); // Crash!
On debugger, workingMessage had only some part of _queue[Index] value.
For example,
_queue[index] : 0x7fffdc09abdb
workingMessage : 0xffdc09abdb
or
_queue[index] : 0x7fffe8048e35
workingMessage : 0x7fffe8040000
like these cases.
I've tried to use std::atomic< Message *> for _queue and workingMessage, same crashes were happened.
What's wrong? I've compiled and tested this on CentOS 7, gcc 4.8.5.

Related

How to make Thread Pool Tasks in abstract function type?

I'm trying to implement very simple C++ Thread Pool.
So far, I've checked it working.
However, I want to make tasks in abstract form.
I've searched for dozens of articles, they don't seem what I want.
(Perhaps my keyword wasn't appropriate...)
Currently, only
void (*)()
form can be accepted as task function.
Simple code is written below.
#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <Windows.h>
class CYSThreadPool
{
private:
static std::thread** s_ppThreads;
static long s_lThreadCount;
static bool s_bJoin;
static std::mutex* s_pMutexJoin;
static std::queue<void (*)()> s_queueTasks;
static std::mutex* s_pMutexTasks;
CYSThreadPool(){}
~CYSThreadPool(){}
static void ThreadFunction()
{
while (true)
{
if (!s_pMutexJoin->try_lock())
continue;
bool bJoin = s_bJoin;
s_pMutexJoin->unlock();
if (bJoin)
break;
if (!s_pMutexTasks->try_lock())
continue;
void (*fp)() = nullptr;
if (s_queueTasks.size() > 0ull)
{
fp = s_queueTasks.front();
s_queueTasks.pop();
}
s_pMutexTasks->unlock();
if (fp != nullptr)
fp();
}
}
public:
enum class EResult : unsigned long
{
Success = 0ul,
Fail_Undefined = 1ul,
Fail_InvalidThreadCount = 2ul,
Fail_ArgumentNull = 3ul
};
static const EResult Join()
{
if (s_ppThreads == nullptr)
{
if (s_lThreadCount == 0l)
return EResult::Success;
else
return EResult::Fail_Undefined;
}
else
{
if (s_lThreadCount <= 0l)
return EResult::Fail_Undefined;
else
{
s_pMutexJoin->lock();
s_bJoin = true;
s_pMutexJoin->unlock();
for (long i = 0l; i < s_lThreadCount; ++i)
{
s_ppThreads[i]->join();
s_ppThreads[i] = nullptr;
}
delete s_ppThreads;
s_ppThreads = nullptr;
s_lThreadCount = 0l;
s_pMutexJoin->lock();
s_bJoin = false;
s_pMutexJoin->unlock();
}
}
return EResult::Success;
}
static const EResult CreateThreads(const long _lThreadCount)
{
if (_lThreadCount < 0l)
return EResult::Fail_InvalidThreadCount;
if (Join() != EResult::Success)
return EResult::Fail_Undefined;
if (_lThreadCount == 0l)
return EResult::Success;
s_ppThreads = new std::thread*[_lThreadCount]{};
for (long i = 0l; i < _lThreadCount; ++i)
s_ppThreads[i] = new std::thread(ThreadFunction);
s_lThreadCount = _lThreadCount;
return EResult::Success;
}
static const EResult AddTask(void (*_fp)())
{
if (_fp == nullptr)
return EResult::Fail_ArgumentNull;
s_pMutexTasks->lock();
s_queueTasks.push(_fp);
s_pMutexTasks->unlock();
return EResult::Success;
}
};
std::thread** CYSThreadPool::s_ppThreads = nullptr;
long CYSThreadPool::s_lThreadCount = 0l;
bool CYSThreadPool::s_bJoin = false;
std::mutex* CYSThreadPool::s_pMutexJoin = new std::mutex();
std::queue<void (*)()> CYSThreadPool::s_queueTasks;
std::mutex* CYSThreadPool::s_pMutexTasks = new std::mutex();
void Test0()
{
for (long i = 0l; i < 100000l; ++i)
{
std::cout << "A";
}
}
int main()
{
CYSThreadPool::EResult eResult = CYSThreadPool::Join();
eResult = CYSThreadPool::CreateThreads(-1l);
eResult = CYSThreadPool::CreateThreads(1l);
eResult = CYSThreadPool::CreateThreads(0l);
eResult = CYSThreadPool::CreateThreads(2l);
CYSThreadPool::AddTask(Test0);
Sleep(1000ul);
CYSThreadPool::Join();
return 0;
}
Kind and elaborated answer will be truly appreciated!
EDIT:
What I meant by 'Function in abstract form' is to get any function types other than void ()().
Such as void ()(long), void ()(ID3D12Resource1, IDXGISwapChain), or HResult ()(ID3D12Device6, ID3D12Resource1*, IDXGISwapChain) and so on.
Thanks for the comment about using condition_variable instead of try_lock and wrapping fp() into try-catch. I'm sorry but I don't think I'm catching what you mean. May I ask for more detail?
So here are few things to improve your code:
You can use std::function<void()> instead of void(*)(). This will allow you to call any callable, not only function pointers, by wrapping them in a lambda, e.g. CYSThreadPool::AddTask([]() { Add(3, 1); });.
Even better, make an abstract base class, say Task with virtual .Run() method and use it instead. You can derive FunctionPointerTask or StdFunctionTask (you can change names obviously) out of it if you want. You can create say ProcessResource1Task and pass necessary arguments to constructor so that .Run() only executes it.
Your ThreadFunction workers are very inefficient. You spin all the time on try_lock. Don't. Use condition_variables instead.
Even better, move the queueing stuff into a separate thread-safe queue class.
Your code is not exception-safe. Don't use manual lock/try_lock, use lock_guard or unique_lock instead. As it is your code can easily deadlock. If you must use manual lock/try_lock then you have to use try-catch.
Lots of static variables. Don't. Make all of them non-static members, add appropriate constructors and destructor. Your thread pool, once joined is completely unusable. Plus Join() is not thread-safe (it would matter less if the thread pool wasn't completely static).
You can improve performance by making bool s_bJoin atomic. It's not necessary to read/write it under the lock.
There might be some other issues, that's what I can see for now.
You can also view this code for a not bad thread pool implementation. It is short and utilizes most of the above hints.

LuaPlus: How to call Lua function from multithreaded C++?

I have a kind of callback function in my Lua script which I would like to call from different threads on the C++ side (0-100 times per second). So far it basically work, but as soon as I call it multiple times in a very short period of time it crashes the program causing errors like:
-As????ion failed: 0, file ...LuaFunction.h, line 146 or this one (completely random)
I think this happens, when it gets called from the C++ side before it finished another task. The most obvious thing for me to try (mutex lock all threads during the lua-function call) didn't help at all. :/
If I only call the Lua-function like once per 2 seconds, then I don't get any errors at all (Well, until the clean up part, if it gets to that point it will crash without a specific error).
Here is my code (I tried to crop and simplify my code as much as possible, and added a lot of commenting):
#include "stdafx.hpp"
#include <pthread.h> //for multithreading
#include <windows.h>
#include <iostream>
#include <map>
using namespace std;
unsigned int maxThreads = 100;
map<unsigned int, pthread_t> threads;
map<unsigned int, bool> threadsState;
pthread_mutex_t mutex; //to lock the pthreads (to keep printing from overlapping etc)
LuaPlus::LuaState* pState = LuaPlus::LuaState::Create( true ); //initialize LuaPlus
LuaPlus::LuaObject globals = pState->GetGlobals();
struct argumentStruct { //to pass multiple arguments to the function called when starting a pthread
unsigned int threadId;
int a;
int b;
};
map<unsigned int, struct argumentStruct> argumentMap; //we store the arguments of active threads in here
void *ThreadFunction(void *arguments) { //will be called for every pthread we're going to create
struct argumentStruct*args = (struct argumentStruct*)arguments; //get the arrgument struct
int threadId = args->threadId; //get variables for each struct field
int a = args->a;
int b = args->b;
Sleep(3000); //since this is a very simplified version of my actual project
int c = a+b;
pthread_mutex_lock(&mutex); //lock pthreads for the next lines
LuaPlus::LuaFunction<int> CPP_OnMyEvent = pState->GetGlobal("LUA_OnMyEvent"); //get the Lua callback function to call on the C++ side
CPP_OnMyEvent(a,b,c); //call to our lua-callback function
pthread_mutex_unlock(&mutex); //unlock pthreads
threadsState[threadId] = false; //mark the thread as finished/ready to get overwritten by a new one
return NULL;
}
bool AddThread(int a, int b) {
for (;;) {
if (threads.size() < maxThreads) { //if our array of threads isn't full yet, create a new thread
int id = threads.size();
argumentMap[id].threadId = threads.size();
argumentMap[id].a = a;
argumentMap[id].b = b;
threadsState[id] = true; //mark the thread as existing/running
pthread_create(&threads[id], NULL, &ThreadFunction, (void *)&argumentMap[id]);
return true;
} else {
unsigned int id;
for (auto thread=threads.begin(); thread!=threads.end(); ++thread) {
id = thread->first;
if(!threadsState[id]) { //if thread with id "id" has finished, create a new thread on it's pthread_t
argumentMap[id].threadId = id;
argumentMap[id].a = a;
argumentMap[id].b = b;
threadsState[id] = true; //mark the thread as existing/running
pthread_join(threads[id], NULL);
pthread_create(&threads[id], NULL, &ThreadFunction, (void *)&argumentMap[id]);
return true;
}
}
}
}
return false;
}
int main() {
pthread_mutex_init(&mutex, NULL); //initialize the mutex
//LuaPlus::LuaState* pState = LuaPlus::LuaState::Create( true ); //we already initialized this globally
//LuaPlus::LuaObject globals = pState->GetGlobals();
//pState->DoString("function LUA_OnMyEvent(arg1,arg2) print(arg1..arg2) end"); //it's already in main.lua
globals.RegisterDirect("AddThread", AddThread);
char pPath[ MAX_PATH ];
GetCurrentDirectory(MAX_PATH,pPath);
strcat_s(pPath,MAX_PATH,"\\main.lua");
if( pState->DoFile(pPath) ) { //run our main.lua script which contains the callback function that will run a print
if( pState->GetTop() == 1 )
std::cout << "An error occured: " << pState->CheckString(1) << std::endl;
}
for (auto thread=threads.begin(); thread!=threads.end(); ++thread) { //wait for threads to finish
unsigned int id = thread->first;
if(threadsState[id])
pthread_join(threads[id], NULL);
}
//clean up
LuaPlus::LuaState::Destroy( pState );
pState = nullptr;
pthread_mutex_destroy(&mutex);
getchar(); //keep console from closing
return 0;
}
main.lua
function LUA_OnMyEvent(a,b,c)
print(a.."+"..b.."="..c)
end
for i=1, 999, 1 do
AddThread(i,i*2)
end
I don't know Lua enough to give you a solution at Lua side, but this view of the problem may help you reaching that out.
When you call AddThread() from Lua, something like this will happen:
1. LuaState allocations
2. AddThread() execution
3. LuaState unwinding
While on ThreadFunction()...
A. Mutex lock
B. LuaState allocations
C. LUA_OnMyEvent() execution
D. LuaState unwinding
E. Mutex Unlock
There is no mutex control at AddThread, so a race condition can happen between 1/3 and B/D.
However, adding the mutex to AddThread would not solve the problem, because it would still run between 1 and 3.
If AddThread() is called only at the program initialization, then you could block all threads till initialization is done. If it is called frequently during program execution, then I would make those calls from a separate LuaState.
[EDIT] 2nd idea: Use a producer/consumer approach. Then C++ threads won't need to run Lua code.
C++ suggestion:
//-- start Task.h --
struct Task{
static list<Task*> runningTasks;
static list<Task*> doneTasks;
static pthread_mutex_t mutex;
list<Task*>::iterator iterator;
virtual ~Task(){}
bool start(){
pthread_mutex_lock(&mutex);
bool hasSpace = runningTasks.size() < 100;
if(hasSpace){
runningTasks.push_front(this);
iterator = runningTasks.begin();
pthread_t unusedID;
pthread_create(&unusedID, NULL, Task::threadBody, this);
}
pthread_mutex_unlock(&mutex);
return hasSpace;
}
virtual void run() = 0;
virtual void processResults() = 0;
protected:
void finish(){
pthread_mutex_lock(&mutex);
runningTasks.erase(iterator);
doneTasks.push_front(this);
pthread_mutex_unlock(&mutex);
}
static void* threadBody(void* instance){
Task* task = static_cast<Task*>(instance);
task->run();
task->finish();
return NULL;
}
};
//-- end Task.h --
//-- start Task.cpp --
//Instantiate Task's static attributes
pthread_mutex_t Task::mutex;
list<Task*> Task::runningTasks;
list<Task*> Task::doneTasks;
//-- end Task.cpp --
struct SumTask: public Task{
int a, b, c;
void run(){
Sleep(3000);
c = a+b;
}
void processResults(){
LuaPlus::LuaFunction<int> CPP_OnMyEvent = pState->GetGlobal("LUA_OnMyEvent");
CPP_OnMyEvent(a,b,c);
}
}
//functions called by Lua
bool runSumTask(int a, int b){
SumTask task* = new SumTask();
task->a = a; task->b = b;
bool ok = task->start();
if(!ok)
delete task;
return ok;
}
int gatherResults(){
pthread_mutex_lock(&Task::mutex);
int totalResults = Task::doneTasks.size();
while(Task::doneTasks.size() > 0){
Task* t = Task::doneTasks.front();
Task::doneTasks.pop_front();
t->processResults();
delete t;
}
pthread_mutex_unlock(&Task::mutex);
return totalResults;
}
int main() {
//Must initialize/destroy Task::mutex
pthread_mutex_init(&Task::mutex, NULL);
//...
pthread_mutex_destroy(&Task::mutex);
}
Lua code:
function LUA_OnMyEvent(a,b,c)
print(a.."+"..b.."="..c)
end
local totalRunning = 0;
for i=1, 999, 1 do
if (runSumTask(i,i*2))
totalRunning = totalRunning + 1;
totalRunning -= gatherResults();
end
while(totalRunning > 0) do
totalRunning -= gatherResults();
mySleepFunction(...);
end

"this" pointer becomes null c++

I have a C++ Qt static library with two classes - dataprocthread and calcvalue. In the first one, when I call a method from an instance of calcvalue, pointer this (which references to dataprocthread class) suddenly becomes null.
This is dataprocthread.h:
class DataProcThread : public QThread
{
Q_OBJECT
public:
DataProcThread(int sarray[9], int val);
signals:
workDone(int result);
private:
int _sarray[9];
int _val;
void run();
};
dataprocthread.cpp:
DataProcThread::DataProcThread(int sarray[9], int val)
{
for (int x = 0; x < 9; x++)
{
_sarray[x] = sarray[x];
}
_val = val;
}
void DataProcThread::run()
{
CalcValue* cv = new CalcValue();
int myval = 0;
for (int i = 0; i < 100; i++)
{
myval = cv->processData(this->_val);
if (this->_sarray[0] != myval)
{
//do something
}
}
emit workDone(intValue);
}
calcvalue.h:
class CalcValue
{
public:
CalcValue();
int processData(int someval);
};
calcvalue.cpp:
CalcValue::CalcValue()
{
}
int processData(int someval)
{
//do something and return int value
}
When I run this code, it suddenly recieves signal "Segmentation fault". Using debugger, I found that the problem in DataProcThread::run() function: when I call cv->processData function, all works good. But on the next line (if (this->_sarray[0] != myval)), this pointer becomes null (I can see it in Locals window), therefore, I can't access this->_sarray variable.
In case it is important, that's how I start the thread (from another class outside my library):
DataProcThread* thread = new DataProcThread(sarray, val);
QObject::connect(thread, SIGNAL(workDone(int)), this, SLOT(collectWork(int)));
thread->start();
What I am doing wrong?
The problem, as was pointed out in comments, took place in processData function: it was writing over memory.
I simply used strncpy instead of strcpy and the problem gone (here is a good explanation about this).

System V IPC & new

I'm new in Linux C and C++ programming. I'm trying to create a C++ class for system v ipc message queue and I have 1 problem.
I wrote class for message like this:
class message
{
friend class queue;
private:
typedef struct
{
long mtype;
char mdata[maxmsg_buf];
}msgbuf_t, *msgbuf_ptr_t;
msgbuf_ptr_t msgbuf_ptr;
public:
message(void):msgbuf_ptr(NULL)
{
msgbuf_ptr = new msgbuf_t;
}
ipc::message::message(const long& type, const std::string& data):msgbuf_ptr(NULL)
{
msgbuf_ptr = new msgbuf_t;
msgbuf_ptr->mtype = type;
if(data.length() <= maxmsg_buf)
{
strncpy(msgbuf_ptr->mdata, data.c_str(), data.length());
}
}
};
class queue
{
private:
mutable qid_t qid;
public:
queue(const key_t& qkey = unique, const perm_t& qperm = usr_rw, const flag_t& qflag = none)
{
qid = msgget(qkey, qperm | qflag);
if(qid == -1)
{
throw errno; //specify exception for queue
}
}
void send(const ipc::message& msg, const int& sflag) const
{
if((msgsnd(qid, &msg.msgbuf_ptr, sizeof(msg.msgbuf_ptr->mdata), sflag)) == -1)
{
throw errno; //specify exception for queue
}
}
};
//Usage:
ipc::queue q(0x0000FFFF, ipc::usr_rw, ipc::create);
ipc::message msg(10L, "First test message for sysVipc queue");
q.send(msg); //throws EFAULT from here
When I send msgbuf_ptr to msgsnd syscall, it returns EFAULT(Bad address) error. So my question is: may I allocate msgbuf using operator new?
P.S. Sorry, if my english is not well.
The problem is in your queue::send method.
&msg.msgbuf_ptr is a pointer to a pointer. Omit the address operator & and you should be fine.
EDIT: no wait
msg.msgbuf_ptr->mdata is your message.
So, you should call it this way:
msgsnd(qid, &msg.msgbuf_ptr + sizeof(msg.msgbuf.mtype), sizeof(msg.msgbuf_ptr->mdata), sflag)

Debug Assertion Failed … _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

I have got a really bad memory leak I am trying to fix, but somehow i am not able to delete Objects without triggering this assertation.
I have searched for a solution via Google and have read the Questions on stackoverflow about this Error but I was still not able to find the answer!
Possible reasons to get this Error according to my research:
1. deleting objects more then one
2. shadow copying
3. creating and deleting Objects that are loaded from an external dll
4. creating objects without storing the pointer
BUT:
1. I checked the code and was not able to find double deletion
2. I use a copy constructor to copy Objects
3. The Error relatet classes are build (with MS Visual Studio) to a seperate lib but not to a dll. AND all the classes that are related to this error are located in the same lib.
4. I checked the code and it seems like that's not the problem
It would be great if anybody is able to spot the mistake in the code below, and I appreciate every hint that points me to the solution of the problem.
EDIT:
I forgot to mention the same deleting problem in sendThreadMain of MessageSystem (see code below). If i delete the Message there it causes unexpected errors somewhere else in the code. Might just be wrong data transmission... but i do not really know.
This code is run on Windows and Linux!
Here are the error related parts of the code:
Message
class Message
{
public:
Message (char type, unsigned char id, unsigned short size)
{
mType = type;
mId = id;
mSize= size;
}
Message(const Message &o)
{
mType = o.mType;
mId = o.mId;
mSize = o.mSize;
}
char getType() const {return mType;};
unsigned char getId() const {return mId;};
unsigned short getSize() const {return mSize;};
protected:
char mType;
unsigned char mId;
unsigned short mSize;
};
class JoinMessage : public Message
{
public:
JoinMessage () : Message ('j', 0, sizeof (JoinMessage))
{
team = TEAM_SPECTATOR;
}
JoinMessage (unsigned char id) : Message ('j', id, sizeof (JoinMessage)){}
JoinMessage (const JoinMessage &o) : Message (o)
{
team = o.team;
setName(o.getName());
}
void setName(std::string newName)
{
if (newName.length() > MAX_PLAYER_NAME_LENGHT)
newName = newName.substr(0, MAX_PLAYER_NAME_LENGHT);
memset(name, 0, MAX_PLAYER_NAME_LENGHT);
for(unsigned int i = 0; i < newName.length(); i++)
name[i] = newName[i];
}
std::string getName() const
{
std::string stringToReturn;
for(unsigned int i = 0; i < MAX_PLAYER_NAME_LENGHT; i++)
{
if (name[i])
stringToReturn.push_back(name[i]);
else
break;
}
return stringToReturn;
}
TeamIdentifier team;
private:
unsigned char name[MAX_PLAYER_NAME_LENGHT];
};
// there are a lot other messages
MessageQueue
MessageQueue::~MessageQueue()
{
boost::mutex::scoped_lock lock (queueMutex);
while(messageQueue.size() > 0)
{
// the crash is non-reproducible
// works 90% of the time
delete messageQueue.front (); // <- Debug Assertion Failed … _BLOCK_TYPE_IS_VALID
messageQueue.pop_front();
}
}
void MessageQueue::enqueMessage (Message* message)
{
{
boost::mutex::scoped_lock lock (queueMutex);
messageQueue.push_back(message);
}
}
Message* MessageQueue::dequeMessage ()
{
boost::mutex::scoped_lock lock (queueMutex);
if (messageQueue.size() == 0)
return nullptr;
Message* message = messageQueue.front ();
messageQueue.pop_front();
return message;
}
MessageSystem
template <class MessageType>
void broadcast (MessageType &message)
{
MessageType *internMessage = new MessageType(message);
boost::mutex::scoped_lock lock (mRecipientMapMutex);
std::map <boost::asio::ip::udp::endpoint, MessageQueue *>::iterator it;
for (it = mRecipientMap.begin ();
it != mRecipientMap.end ();
it++)
{
it->second->enqueMessage(internMessage);
}
}
template <class MessageType>
void post (MessageType &message, boost::asio::ip::udp::endpoint &recipient)
{
MessageType *internMessage = new MessageType(message);
std::map <boost::asio::ip::udp::endpoint, MessageQueue* >::iterator it;
MessageQueue *messageQueue = NULL;
{
boost::mutex::scoped_lock lock (mRecipientMapMutex);
it = mRecipientMap.find (recipient);
if (it != mRecipientMap.end())
messageQueue = it->second;
if(messageQueue)
messageQueue->enqueMessage (internMessage);
}
}
void MessageSystem::sendThreadMain ()
{
// copy endpoints to vecotr so it can be
// deleted from map while iterating
std::vector<udp::endpoint> endpoints;
{
boost::mutex::scoped_lock lock (mRecipientMapMutex);
std::map <udp::endpoint, MessageQueue *>::iterator mapIt = mRecipientMap.begin ();
while (mapIt != mRecipientMap.end())
{
endpoints.push_back(mapIt->first);
mapIt++;
}
}
std::vector<udp::endpoint>::iterator endpointIt = endpoints.begin();
while (endpointIt != endpoints.end())
{
char sendBuffer[PACKET_SIZE];
int sendBufferPosition = 0;
{
boost::mutex::scoped_lock lock (mRecipientMapMutex);
MessageQueue *messageQueue = mRecipientMap[*endpointIt];
if (messageQueue == nullptr)
{
mRecipientMap.erase(*endpointIt);
endpointIt++;
continue;
}
while (Message *message = messageQueue->dequeMessage ())
{
if (sendBufferPosition + message->getSize() > PACKET_SIZE)
{
// put message back and send it later
messageQueue->enqueMessage (message);
break;
}
// copy message into buffer
std::memcpy (
&sendBuffer [sendBufferPosition], message, message->getSize());
sendBufferPosition += message->getSize();
// deleting this message causes a crash if 2 or more
// recipients are registered within MessageSystem
//delete message; <- RANDOM CRASH elsewhere in the program
}
}
.... // more code down here that seems not related to the error
Today I figured it out on my own. It was #1 of the 4 possibilities mentioned in the Question.
deleting objects more then once (by saving multiple pointers to the exact same object)
Here is my Solution in MessageQueue:
template <class MessageType>
void broadcast (MessageType &message)
{
// I was creating 1 new Message right here but I need 1 new Message
// in EVERY MessageQueue so i moved the next line ...
// MessageType *internMessage = new MessageType(message);
boost::mutex::scoped_lock lock (mRecipientMapMutex);
std::map <boost::asio::ip::udp::endpoint, MessageQueue *>::iterator it;
for (it = mRecipientMap.begin ();
it != mRecipientMap.end ();
it++)
{
// ... down here. Now every queue contains its own copy of the Message
MessageType *internMessage = new MessageType(message);
it->second->enqueMessage(internMessage);
}
}
It might be a simple problem of wrong order. You are doing:
while(messageQueue.size() > 0)
{
delete messageQueue.front();
messageQueue.pop_front();
}
Maybe deleting the message after popping it, instead of before, would do the trick:
while(messageQueue.size() > 0)
{
Message* pFront = messageQueue.front();
messageQueue.pop_front();
delete pFront;
}
Anyway, I am not confident at all on this solution, since deleting the object pointed by pFront should have no effect on the queue itself, which just stores pointers. But you can try.
Well, I faced similar problem,
the following code
Message* message = messageQueue.front ();
messageQueue.pop_front();
return message;
The code that produced error with me was:
Point *p = q.LookFor(&q, &pts[5], &Dist);
cout ...
delete p;
It seems that the function delete the pointer it creates in the runtime, so you're not allowed to delete it "again"
so I replaced it with
Point p = *(q.LookFor(&q, &pts[5], &Dist));
and it's gone.