2

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)
kiner_shah
  • 3,939
  • 7
  • 23
  • 37
long.kl
  • 670
  • 4
  • 12
  • Does this answer your question? [why does std::allocator::deallocate require a size?](https://stackoverflow.com/questions/38771551/why-does-stdallocatordeallocate-require-a-size) – user17732522 Dec 28 '21 at 10:34
  • Using incorrect size to `deallocate` violates its precondition, resulting in undefined behavior. But that doesn't mean the function actually needs to use that argument. Why it is there when it is not typically used is explained in the linked question. – user17732522 Dec 28 '21 at 10:35
  • Yes, @user17732522 Thanks, undefined behavior quite ambiguous for me. I ran the test amount of time because I think debug tool like valgrind or static analysis can detect the problem. – long.kl Dec 28 '21 at 11:00
  • 1
    "Undefined behavior" means that there is no guarantee made by the C++ standard about anything. It doesn't guarantee that the program will work or will not work. Analyzers of any kind can not generally detect undefined behavior, especially not in a case like this where you are just violating a standard library precondition that in practice might not matter. – user17732522 Dec 28 '21 at 11:22
  • See also https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior – user17732522 Dec 28 '21 at 11:22

3 Answers3

0
  1. testcase2 "test_deallocate" : I deallocate with size(0) less than actual size (400),valgrind or -fsanitize=address can't detect leak

When you dellocate with wrong size, then the behaviour of the program is undefined. When the behaviour is undefined, there is no guarantee that memory would be leaked.

  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.

Ditto.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

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.

Paul Floyd
  • 5,530
  • 5
  • 29
  • 43
0

I checked libstdc++ which used in the testcases.
I saw that currently size argument for std::allocator::deallocate is unused. it call delete, same with new/delete operator operation, it don't need size anymore.

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

long.kl
  • 670
  • 4
  • 12