std::allocator 解除分配不使用大小参数

std::allocator deallocate don't use size argument

我正在了解 std::allocator。我尝试分配但错误地使用 deallocate 我看到它没有使用大小参数,我对这个方法感到困惑,你能为我解释一下吗?谢谢。

  1. testcase1“测试”:我没有解除分配,检测到 valgrind(正确)
  2. testcase2“test_deallocate”:我释放了小于实际大小 (400) 的大小 (0),valgrind 或 -fsanitize=address 无法检测到泄漏
  3. testcase3“test_deallocate2”:我释放大小(10000)大于实际大小(400)编译器没有警告,g++ -fsanitize=address 也无法检测到这一点。
    #include <iostream>
    #include <memory>
    
    using namespace std;
    void test(){
    
        allocator<int> al;
        int* bl = al.allocate(100);
    }
    
    void test_deallocate(){
    
        allocator<int> al;
        int* bl = al.allocate(100);
        al.deallocate(bl, 0);
    }
    
    void test_deallocate2(){
    
        allocator<int> al;
        int* bl = al.allocate(100);
        al.deallocate(bl, 10000);
    }
    
    int main(){
       
        test();
        test_deallocate();
        test_deallocate2();
        return 0;
    }

瓦尔格林德:

    valgrind --leak-check=full ./a.out  
    ==12655== Memcheck, a memory error detector
    ==12655== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==12655== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
    ==12655== Command: ./a.out
    ==12655== 
    ==12655== 
    ==12655== HEAP SUMMARY:
    ==12655==     in use at exit: 400 bytes in 1 blocks
    ==12655==   total heap usage: 4 allocs, 3 frees, 73,904 bytes allocated
    ==12655== 
    ==12655== 400 bytes in 1 blocks are definitely lost in loss record 1 of 1
    ==12655==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==12655==    by 0x1090D1: allocate (new_allocator.h:114)
    ==12655==    by 0x1090D1: test (test.cpp:8)
    ==12655==    by 0x1090D1: main (test.cpp:27)
    ==12655== 
    ==12655== LEAK SUMMARY:
    ==12655==    definitely lost: 400 bytes in 1 blocks
    ==12655==    indirectly lost: 0 bytes in 0 blocks
    ==12655==      possibly lost: 0 bytes in 0 blocks
    ==12655==    still reachable: 0 bytes in 0 blocks
    ==12655==         suppressed: 0 bytes in 0 blocks
    ==12655== 
    ==12655== For lists of detected and suppressed errors, rerun with: -s
    ==12655== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
  1. testcase2 "test_deallocate" : I deallocate with size(0) less than actual size (400),valgrind or -fsanitize=address can't detect leak

当你分配错误的大小时,程序的行为是未定义的。当行为未定义时,无法保证内存会泄漏。

  1. testcase3 "test_deallocate2": I deallocate with size(10000) greater than actual size (400) compiler didn't warning , g++ with -fsanitize=address also can't detect this.

同上。

Valgrind 仅拦截较低级别的分配函数(malloc、new 等)。所以这完全取决于 allocatedeallocate 的实现。

目前 Valgrind 没有对大小删除做太多检查(或对齐新的,参见 and https://bugs.kde.org/show_bug.cgi?id=433859)。

我可能会在 2022 年为这些实现一些东西。

如果您使用 GCC libstdc++ 或 clang libc++,那么它们的大小删除不会执行任何特殊操作,它们只是调用普通删除。我还没找 deallocate.

我检查了测试用例中使用的 libstdc++。
我看到 std::allocator::deallocate 的当前大小参数未使用。它调用删除,与new/delete运算符操作相同,它不再需要大小。

00096       void
00097       deallocate(pointer __p, size_type)
00098       { ::operator delete(__p); }

https://gcc.gnu.org/onlinedocs/gcc-4.6.2/libstdc++/api/a00958_source.html