【问题标题】:Delete aligned memory from another thread从另一个线程中删除对齐的内存
【发布时间】:2014-03-04 17:22:44
【问题描述】:

(C++) 我在堆上分配了内存对齐的实例,然后在另一个线程中删除它们。代码如下所示:

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

线程 2 中的删除语句将在 Visual Studio 2013 (_BLOCK_TYPE_IS_VALID) 中给出断言错误。 奇怪的是,如果我在创建线程中删除对象,一切运行正常。

为什么会这样?解决办法是什么?

编辑:

@galop1n:实际上我目前使用的是 Eigen 的内置新/删除运算符 EIGEN_MAKE_ALIGNED_OPERATOR_NEW。我也尝试了自己的运算符,都失败了。

对于 Eigen 的运算符,请自行查找其来源。

对于我的分配器:

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

而 ALIGNED 宏是 __declspec(align(16))。无论有没有“对齐”属性,它都会崩溃。

【问题讨论】:

  • 在调用delete 之前,您是否真的在等待构造o
  • @mfukar:是的,一切都完美同步。实际上,如果我创建非对齐实例,删除语句运行良好。
  • @Defd 然后它必须处理你的自定义分配器。
  • 您是否正在链接您的 tuntime 库的多线程版本?
  • 什么是 ALIGNED 和 ALIGNED_NEW_DELETE?这些不是 C++ 关键字。如果您将它们#define 定义为其他内容,请提示我们...

标签: c++ multithreading memory simd eigen


【解决方案1】:

这很尴尬,问题出在线程 2 中,Obj* 被强制转换为基类的指针 Task*,并且完全愚蠢:~Task() 不是虚拟的:

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

ALIGNED class Obj : public Task 
{ ... }

应该更早发现这个问题。因为,正如我对问题的描述,我自己说它给出了一个断言错误:_BLOCK_TYPE_IS_VALID,这是一个 Visual Studio 调试库的默认删除运算符的东西,这意味着它甚至没有遇到我的重载删除运算符,这最终意味着我错过了一个“虚拟”。

我什至忘记在问题中添加类继承是我的错。

有时,我可能会被一个问题困住数小时甚至数天。但是在我把问题发到网上后,我马上就能找到答案。不知道你们之前是否有类似的问题;也许我给自己施加了太大的压力。

仍然,谢谢你,互联网。

【讨论】:

  • 总是这样:一旦我遇到一个数小时都无法解决的难题,我会尝试将问题表述为一个综合问题,以便在 SO 上发布 - 只是为了意识到实际上有一个明显并且通常是解决这个问题的简单方法;)
  • 没有人能想到这一点,因为您忽略了最重要的细节……在调用 delete 之前,您实际上在第二个线程中投射了一个指针。这就是所谓的 XY 问题 (meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。问题与线程无关,但你的标题是“从另一个线程中删除对齐的内存”。
  • @thang:是的。我决定保留这个问题,因为它表明提问者可以忽略重要的细节。同样的问题发生在所有行业,一些伟大的发现甚至源于这些看似不重要的特征,尤其是在数学和物理学中。对于所有阅读此问题的人,请从我的错误中吸取教训。
猜你喜欢
  • 2015-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-03
  • 2012-08-04
  • 2011-10-12
  • 2013-01-12
  • 1970-01-01
相关资源
最近更新 更多