如何正确调用对齐的新/删除? [英] How to invoke aligned new/delete properly?

查看:99
本文介绍了如何正确调用对齐的新/删除?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何通过对齐方式调用 new 运算符?

How do I call new operator with alignment?

auto foo = new(std::align_val_t(32)) Foo; //?

然后如何正确删除它?

delete(std::align_val_t(32), foo); //?

如果这是使用这些重载的正确形式,为什么还要抱怨抱怨free()/delete/delete []不匹配?

If this is the right form of using these overloads, why valgring complaining about mismatched free()/delete/delete[]?

推荐答案

存在非常基本的原则-空闲内存例程必须始终与分配例程匹配.如果我们使用不匹配分配和空闲,则运行时行为可以是任意的:所有行为都可以是随机的,运行时崩溃,内存泄漏或堆损坏.

exist very basic principle - the memory free routine always must match to allocate routine. if we use mismatch allocate and free - run time behavior can be any: all can be random ok, or crash by run-time, or memory leak, or heap corruption.

如果我们使用操作符new的对齐版本分配内存

if we allocate memory with aligned version of operator new

void* operator new  ( std::size_t count, std::align_val_t al);

我们必须使用相应的对齐版本的运算符删除

we must use the corresponding aligned version of operator delete

void operator delete  ( void* ptr, std::align_val_t al );

调用 void运算符delete(void * ptr); 总是必须导致运行时错误.让我们简单地测试

call void operator delete ( void* ptr ); here always must lead to run-time error. let simply test

    std::align_val_t al = (std::align_val_t)256;
    if (void* pv = operator new(8, al))
    {
        operator delete(pv, al);
        //operator delete(pv); this line crash, or silently corrupt heap
    }

为什么 operator delete 的对齐版本与不对齐版本始终不兼容?让我们想想-如何在某些价值记忆上分配 align ?我们最初总是分配一些内存块.供返回的 align 指针使用-我们需要将分配的内存指针调整为多次对齐.好的.这可以通过分配比请求更多的内存并调整指针来实现.但是,现在的问题是:该块有多免费?通常,用户获得的指针不指向分配的内存的开头-如何从该用户指针跳回分配的块的开头?没有其他信息,这是不可能的.我们需要在用户返回指针之前存储指向实际分配的内存的指针.可能会在使用 _aligned_free

why is aligned and not aligned version of operator delete always incompatible ? let think - how is possible allocate align on some value memory ? we initially always allocate some memory block. for return align pointer to use - we need adjust allocated memory pointer to be multiple align. ok. this is possible by allocate more memory than requested and adjust pointer. but now question - how free this block ? in general user got pointer not to the begin of allocated memory - how from this user pointer jump back to begin of allocated block ? without additional info this is impossible. we need store pointer to actual allocated memory before user returned pointer. may be this will be more visible in code typical implementation for aligned new and delete use _aligned_malloc and _aligned_free

void* operator new(size_t size, std::align_val_t al)
{
    return _aligned_malloc(size, static_cast<size_t>(al));
}

void operator delete  (void * p, std::align_val_t al)
{
    _aligned_free(p);
}

未对齐时 new delete 使用 malloc free

void* operator new(size_t size)
{
    return malloc(size);
}

void operator delete  (void * p)
{
    free(p);
}

现在让我们寻找 _aligned_malloc

now let look for internal implementation of _aligned_malloc and _aligned_free

void* __cdecl _aligned_malloc(size_t size, size_t alignment)
{
    if (!alignment || ((alignment - 1) & alignment))
    {
        // alignment is not a power of 2 or is zero
        return 0;
    }

    union {
        void* pv;
        void** ppv;
        uintptr_t up;
    };

    if (void* buf = malloc(size + sizeof(void*) + --alignment))
    {
        pv = buf;
        up = (up + sizeof(void*) + alignment) & ~alignment;
        ppv[-1] = buf;

        return pv;
    }

    return 0;
}

void __cdecl _aligned_free(void * pv)
{
    if (pv)
    {
        free(((void**)pv)[-1]);
    }
}

一般而言, _aligned_malloc 分配 size + sizeof(void *)+对齐​​方式-1 ,而不是调用方 size 所请求.调整分配的指针以适合对齐方式,并在指针返回到调用者之前存储最初分配的内存.

in general words _aligned_malloc allocate size + sizeof(void*) + alignment - 1 instead requested by caller size. adjust allocated pointer to fit alignment , and store originally allocated memory before pointer returned to caller.

_aligned_free(pv)调用不是 free(pv),而是 free(((void **)pv)[-1]); -用于总是另一个指针.因为 _aligned_free(pv)的这种效果总是与另一个 free(pv)进行比较.和 operator delete(pv,al); 始终与 operator delete(pv); 不兼容,如果说 delete [] 通常具有相同的效果作为 delete 删除,但align vs not align的运行时间总是不同的.

and _aligned_free(pv) call not free(pv) but free(((void**)pv)[-1]); - for always another pointer. because this effect of _aligned_free(pv) always another compare free(pv). and operator delete(pv, al); always not compatible with operator delete(pv); if say delete [] usual have the same effect as delete but align vs not align always run time different.

这篇关于如何正确调用对齐的新/删除?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆