Search code examples
c++g++valgrindallocator

std::allocator deallocate don't use size argument


I'm learn about std::allocator. I try to allocate but use deallocate incorrectly I saw that it didn't use size argument, I confuse about the method could you please explain for me ? Thanks.

  1. testcase1 "test" : I didn't deallocate, valgrind detected (correct)
  2. testcase2 "test_deallocate" : I deallocate with size(0) less than actual size (400),valgrind or -fsanitize=address can't detect leak
  3. 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.
    #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:

    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)

Solution

  • Valgrind only intercepts the lower level allocation functions (malloc, new etc.). So it all depends on what the implementation of allocate and deallocate do.

    Currently Valgrind doesn't do much checking of sized delete (or aligned new for that matter, see why does std::allocator::deallocate require a size? and https://bugs.kde.org/show_bug.cgi?id=433859).

    I may implement something for these in 2022.

    If you use GCC libstdc++ or clang libc++ then their sized deletes do not do anything special, they just call plain delete. I haven't looked for deallocate.