Удаление указателя иногда приводит к повреждению кучи
У меня есть многопоточное приложение, которое работает с использованием пользовательского класса пула потоков. Все потоки выполняют одну и ту же функцию с разными параметрами.
Эти параметры передаются классу threadpool следующим образом:
// jobParams is a struct of int, double, etc...
jobParams* params = new jobParams;
params.value1 = 2;
params.value2 = 3;
int jobId = 0;
threadPool.addJob(jobId, params);
Как только потоку нечего делать, он получает следующие параметры и запускает функцию задания. Я решил позаботиться об удалении параметров в классе threadpool:
ThreadPool::~ThreadPool() {
for (int i = 0; i < this->jobs.size(); ++i) {
delete this->jobs[i].params;
}
}
Однако при этом я иногда получаю ошибку повреждения кучи:
Указан неверный адрес для RtlFreeHeap
Странно то, что в одном случае это работает отлично, но в другой программе происходит сбой с этой ошибкой. Я попытался удалить указатель в других местах: в потоке после выполнения функции задания (я получаю ту же ошибку повреждения кучи) или в конце самой функции задания (в этом случае ошибки нет).
Я не понимаю, как удаление одних и тех же указателей (я проверял, адреса одинаковые) из разных мест что-то меняет. Это как-то связано с тем, что он многопоточный?
У меня есть критическая секция, которая обрабатывает доступ к параметрам. Я не думаю, что проблема заключается в синхронизированном доступе. В любом случае, деструктор вызывается только после того, как все потоки завершены, и я нигде больше не удаляю указатель. Можно ли автоматически удалить указатель?
Что касается моего кода. Список заданий представляет собой очередь структуры, состоящую из идентификатора задания (использовавшегося для того, чтобы позднее получить возможность получить результат конкретного задания) и параметров.
getNextJob()
вызывается потоками (у них есть указатель на ThreadPool) каждый раз, когда они заканчивают выполнять свое последнее задание.
void ThreadPool::addJob(int jobId, void* params) {
jobData job; // jobData is a simple struct { int, void* }
job.ID = jobId;
job.params = params;
// insert parameters in the list
this->jobs.push(job);
}
jobData* ThreadPool::getNextJob() {
// get the data of the next job
jobData* job = NULL;
// we don't want to start a same job twice,
// so we make sure that we are only one at a time in this part
WaitForSingleObject(this->mutex, INFINITE);
if (!this->jobs.empty())
{
job = &(this->jobs.front());
this->jobs.pop();
}
// we're done with the exclusive part !
ReleaseMutex(this->mutex);
return job;
}