Question

(C++) I have memory aligned instances allocated on heap, then delete them in another thread. The codes look like this:

ALIGNED class Obj
{
public: ALIGNED_NEW_DELETE
...
};

Thread 1:
Obj *o = new Obj;  // overloaded new for aligned memory allocation
postTask(o);

Thread 2:
o->runTask();
delete o;  // overloaded delete for aligned memory deletion
// "delete" statement crashes

The delete statement in thread 2 will give an assertion error in Visual Studio 2013 (_BLOCK_TYPE_IS_VALID). Strangely, if i delete the object in the creation thread, everything runs fine.

Why does this happen? What's the solution?

EDIT:

@galop1n: Actually what i am currently using is Eigen's built-in new/delete operators EIGEN_MAKE_ALIGNED_OPERATOR_NEW. I also tried my own operators, both failed.

For Eigen's operators, please look up its source yourself.

For my allocators:

void* operator new(size_t size){ return alignedMalloc(size, align); }
void operator delete(void* ptr) { alignedFree(ptr); } 
void* operator new[](size_t size) { return alignedMalloc(size, align); }
void operator delete[](void* ptr) { alignedFree(ptr); }  


void* alignedMalloc(size_t size, size_t align)
{
    char* base = (char*)malloc(size + align + sizeof(int));
    if (base == nullptr) 
           ASSERT(0, "memory allocation failed");
    char* unaligned = base + sizeof(int);
    char* aligned = unaligned + align - ((size_t)unaligned & (align - 1));
    ((int*)aligned)[-1] = (int)((size_t)aligned - (size_t)base);
    return aligned;
}

void alignedFree(const void* ptr) {
    int ofs = ((int*)ptr)[-1];
    free((char*)ptr - ofs);
}

And the ALIGNED macro is __declspec(align(16)). It crashes with or without the "ALIGNED" attribute.

Était-ce utile?

La solution

This is awkward, the problem is in Thread 2, The Obj* is casted into a base class' pointer Task*, and for the utter stupidity: ~Task() is not virtual:

class Task 
{
public:
  ~Task();  // <-- not virtual, therefore it crashes
  ...
}

ALIGNED class Obj : public Task 
{ ... }

Should have discovered this problem much much earlier. Because, as in my description of the problem, i said it myself it gives an assertion error: _BLOCK_TYPE_IS_VALID, this is a visual studio debug lib's stuff for the default delete operator, which means it didn't even run into my overloaded delete operator, which ultimately means I missed a "virtual".

It's my bad that i even forgot to add the class inheritance to the question.

Sometimes, i can be stuck at a problem for hours or even days. But after i posted the issue online, i can immediately find the answer. Dunno if any of you have similar problems before; perhaps i've put too much stress onto myself.

Still, thanks you, Internet.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top