You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASan报new_delete_type_mismatch:对齐new需配对对齐delete吗?

对齐new/delete配对问题与ASan报错解析

问题重现

以下代码用g++ 14.2.1加-Wall -pedantic编译无警告,运行正常,但启用-fsanitize=address后,ASan抛出类型不匹配错误:

#include <new>
int main() {
    delete new (std::align_val_t(16)) char;
}

ASan报错内容:

==17707==ERROR: AddressSanitizer: new-delete-type-mismatch on 0x503000000040 in thread T0:
  object passed to delete has wrong type:
  size of the allocated type:   1 bytes;
  size of the deallocated type: 1 bytes.
  alignment of the allocated type:   16 bytes;
  alignment of the deallocated type: default-aligned.
    #0 0x70912beff4f2 in operator delete(void*, unsigned long) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:164
    #1 0x6493bc2dd18d in main (/tmp/a.out+0x118d) (BuildId: e8f06d0aee8e301d7f1522801237096f3006c790)
    #2 0x70912b835487  (/usr/lib/libc.so.6+0x27487) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #3 0x70912b83554b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #4 0x6493bc2dd094 in _start (/tmp/a.out+0x1094) (BuildId: e8f06d0aee8e301d7f1522801237096f3006c790)

0x503000000040 is located 0 bytes inside of 1-byte region [0x503000000040,0x503000000041)
allocated by thread T0 here:
    #0 0x70912befe97a in operator new(unsigned long, std::align_val_t) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:107
    #1 0x6493bc2dd17b in main (/tmp/a.out+0x117b) (BuildId: e8f06d0aee8e301d7f1522801237096f3006c790)
    #2 0x70912b835487  (/usr/lib/libc.so.6+0x27487) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #3 0x70912b83554b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #4 0x6493bc2dd094 in _start (/tmp/a.out+0x1094) (BuildId: e8f06d0aee8e301d7f1522801237096f3006c790)

SUMMARY: AddressSanitizer: new-delete-type-mismatch /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:164 in operator delete(void*, unsigned long)

核心问题解答

  1. 这是不是ASan的误报?
    不是误报。ASan准确检测到了分配和释放时的对齐属性不匹配——用16字节对齐的new分配内存,却用默认对齐的delete释放,这属于标准定义的问题场景。

  2. 必须将对齐new和对齐delete配对吗?
    是的,必须配对。根据C++标准[new.delete]章节的规定:用带std::align_val_t参数的operator new分配的内存,必须用带对应std::align_val_t参数的operator delete来释放。

  3. 不配对会导致未定义行为吗?
    会。标准明确指出,这种不匹配的释放操作属于未定义行为。虽然某些编译器/平台下可能“看起来正常”,但这完全依赖实现细节,移植性和稳定性无法保证,极端情况下可能导致内存泄露、堆损坏或程序崩溃。

过度对齐内存释放的最佳实践

对于SIMD场景中32字节对齐的double数组这类过度对齐内存,最佳实践如下:

  • 显式调用带对齐参数的operator delete:分配时用new (std::align_val_t(32)) double[N],释放时必须对应调用operator delete[](ptr, std::align_val_t(32)),数组版的对齐new要对应数组版的对齐delete。
  • 避免裸指针管理:优先使用智能指针,并自定义删除器来确保对齐释放。示例:
    #include <memory>
    #include <new>
    
    int main() {
        constexpr std::size_t align = 32;
        auto deleter = [](double* p) {
            operator delete[](p, std::align_val_t(align));
        };
        std::unique_ptr<double, decltype(deleter)> ptr(
            new (std::align_val_t(align)) double[8], deleter
        );
    }
    
  • 用std::aligned_alloc替代(C风格分配):如果用C风格的std::aligned_alloc分配,必须用std::free释放,但要注意std::aligned_alloc的大小必须是对齐值的整数倍,这点和C++的对齐new不同。

内容的提问来源于stack exchange,提问作者YiFei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 12:57:01