Usunięcie wskaźnika czasami powoduje uszkodzenie sterty

Mam aplikację wielowątkową, która działa przy użyciu niestandardowej klasy puli wątków. Wszystkie wątki wykonują tę samą funkcję, z różnymi parametrami.

Parametry te są podane klasie threadpool w następujący sposób:

// 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);

Gdy tylko wątek nie ma nic do roboty, pobiera kolejne parametry i uruchamia funkcję zadania. Postanowiłem zadbać o usunięcie parametrów w klasie threadpool:

ThreadPool::~ThreadPool() {
    for (int i = 0; i < this->jobs.size(); ++i) {
        delete this->jobs[i].params;
    }
}

Jednak w takim przypadku czasami pojawia się błąd uszkodzenia sterty:

Nieprawidłowy adres podany w RtlFreeHeap

Dziwne jest to, że w jednym przypadku działa doskonale, ale w innym programie ulega awarii z tym błędem. Próbowałem usunąć wskaźnik w innych miejscach: w wątku po wykonaniu funkcji zadania (otrzymuję ten sam błąd uszkodzenia sterty) lub na końcu samej funkcji zadania (w tym przypadku brak błędu).

Nie rozumiem, jak usuwanie tych samych wskaźników (sprawdziłem, że adresy są takie same) z różnych miejsc zmienia cokolwiek. Czy ma to coś wspólnego z faktem, że jest wielowątkowy?

Mam sekcję krytyczną, która obsługuje dostęp do parametrów. Nie sądzę, aby problem dotyczył zsynchronizowanego dostępu. W każdym razie destruktor jest wywoływany tylko po wykonaniu wszystkich wątków i nie usuwam żadnego wskaźnika w żadnym innym miejscu. Czy wskaźnik może zostać automatycznie usunięty?

Co do mojego kodu. Lista zadań jest kolejką struktury, składającą się z identyfikatora zadania (używanego do uzyskania późniejszego wyniku określonego zadania) i parametrów.

getNextJob() jest wywoływany przez wątki (mają wskaźnik do Puli wątków) za każdym razem, gdy zakończyli wykonywanie ostatniego zadania.

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;
}

questionAnswers(7)

yourAnswerToTheQuestion