【问题标题】:std::allocator deallocate don't use size argumentstd::allocator deallocate 不使用大小参数
【发布时间】:2021-12-28 10:28:30
【问题描述】:

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

  1. testcase1 "test" : 我没有解除分配,检测到 valgrind(正确)
  2. testcase2 "test_deallocate" : 我释放的 size(0) 小于实际大小 (400),valgrind 或 -fsanitize=address 无法检测到泄漏
  3. testcase3 "test_deallocate2": 我在 size(10000) 大于实际大小 (400) 的情况下解除分配,编译器没有警告,带有 -fsanitize=address 的 g++ 也无法检测到这一点。
    #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)

【问题讨论】:

  • deallocate 使用不正确的大小违反了其先决条件,导致未定义的行为。但这并不意味着该函数实际上需要使用该参数。链接问题中解释了为什么它在通常不使用时存在。
  • 是的,@user17732522 谢谢,未定义的行为对我来说很模糊。我运行了一段时间的测试,因为我认为 valgrind 或静态分析之类的调试工具可以检测到问题。
  • “未定义行为”意味着 C++ 标准不保证任何事情。它不保证该程序会运行或不会运行。任何类型的分析器通常都无法检测到未定义的行为,尤其是在这种情况下,您只是违反了实际上可能无关紧要的标准库先决条件。

标签: c++ g++ valgrind allocator


【解决方案1】:

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

目前 Valgrind 并没有对大小删除做太多检查(或对齐新的,请参阅 why does std::allocator::deallocate require a size?https://bugs.kde.org/show_bug.cgi?id=433859)。

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

如果您使用 GCC libstdc++ 或 clang libc++,那么它们的大小删除不会做任何特别的事情,它们只是调用普通删除。我还没找deallocate

【讨论】:

  • 谢谢。我认为要弄清楚这个问题,我应该检查分配/解除分配源。
【解决方案2】:
  1. testcase2 "test_deallocate" : 我释放的 size(0) 小于实际大小 (400),valgrind 或 -fsanitize=address 无法检测到泄漏

当您使用错误的大小进行 delocate 时,程序的行为是未定义的。当行为未定义时,无法保证内存会泄漏。

  1. testcase3 "test_deallocate2":我在 size(10000) 大于实际大小 (400) 的情况下解除分配,编译器没有警告,带有 -fsanitize=address 的 g++ 也无法检测到这一点。

同上。

【讨论】:

  • 谢谢,未定义的行为对我来说很模糊。我运行了测试时间,因为我认为 valgrind 或静态分析之类的调试工具可以检测到问题
  • @long.kl 尝试使用地址消毒剂。
  • 谢谢@eerorika 我会试试的。
【解决方案3】:

我检查了测试用例中使用的 libstdc++。
我看到 std::allocator::deallocate 的当前大小参数未使用。它调用delete,与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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-14
    • 1970-01-01
    • 1970-01-01
    • 2021-08-14
    • 1970-01-01
    • 2011-12-12
    • 1970-01-01
    相关资源
    最近更新 更多