1

以下代码

#include <vector>
#include <string>
#include <iostream>

struct Type
{
    std::string a;
};

int main()
{
    std::vector<unsigned char> data;

    data.resize(sizeof(Type));

    Type* a = new (&data[0]) Type({"something"});

    data.resize(sizeof(Type)*2);

    Type* b = new (&data[sizeof(Type)]) Type({"else"});

    Type* ts = reinterpret_cast<Type*>(&data[0]);

    for(std::size_t i = 0; i < 2; ++i)
    {
        std::cout << ts[i].a << std::endl;
        ts[i].~Type();
    }

    return 0;
}

从 Dr Memory 产生这个输出

Dr. Memory version 2.2.0 build 1 built on Jul  1 2019 00:42:20
Windows version: WinVer=105;Rel=1909;Build=18363;Edition=Enterprise
Dr. Memory results for pid 14664: "CPPTests.exe"
Application cmdline: "bin/Debug/CPPTests.exe -callstack_max_frames 40 -malloc_max_frames 40 -free_max_frames 40"
Recorded 117 suppression(s) from default C:\Program Files (x86)\Dr. Memory\bin\suppress-default.txt

Error #1: UNADDRESSABLE ACCESS of freed memory: reading 0x01750568-0x01750569 1 byte(s)
# 0 msvcrt.dll!_fwrite_nolock
# 1 msvcrt.dll!fwrite    
# 2 libstdc++-6.dll!?                +0x0      (0x6fe5cf56 <libstdc++-6.dll+0x1cf56>)
# 3 libstdc++-6.dll!?                +0x0      (0x6ff23d80 <libstdc++-6.dll+0xe3d80>)
# 4 _fu0___ZSt4cout                   [C:/tests.cpp:26]
# 5 __tmainCRTStartup                 [D:/mingwbuild/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:335]
# 6 KERNEL32.dll!BaseThreadInitThunk +0x18     (0x75306359 <KERNEL32.dll+0x16359>)
Note: @0:00:00.608 in thread 3732
Note: next higher malloc: 0x01750598-0x017505c8
Note: prev lower malloc:  0x01750468-0x0175046b
Note: 0x01750568-0x01750569 overlaps memory 0x01750560-0x01750578 that was freed here:
Note: # 0 replace_operator_delete                              [d:\drmemory_package\common\alloc_replace.c:2975]
Note: # 1 __gnu_cxx::new_allocator<>::deallocate               [C:/MSYS2-32/mingw32/include/c++/10.1.0/ext/new_allocator.h:133]
Note: # 2 std::allocator_traits<>::deallocate                  [C:/MSYS2-32/mingw32/include/c++/10.1.0/bits/allocator.h:187]
Note: # 3 std::_Vector_base<>::_M_deallocate                   [C:/MSYS2-32/mingw32/include/c++/10.1.0/bits/stl_vector.h:354]
Note: # 4 std::vector<>::_M_default_append                     [C:/MSYS2-32/mingw32/include/c++/10.1.0/bits/vector.tcc:675]
Note: # 5 std::vector<>::resize                                [C:/MSYS2-32/mingw32/include/c++/10.1.0/bits/stl_vector.h:940]
Note: instruction: movsx  (%eax) -> %eax

Error #2: INVALID HEAP ARGUMENT to free 0x01750568
# 0 replace_operator_delete                                   [d:\drmemory_package\common\alloc_replace.c:2975]
# 1 __gnu_cxx::new_allocator<>::deallocate                    [C:/MSYS2-32/mingw32/include/c++/10.1.0/ext/new_allocator.h:133]
# 2 std::allocator_traits<>::deallocate                       [C:/MSYS2-32/mingw32/include/c++/10.1.0/bits/allocator.h:187]
# 3 std::__cxx11::basic_string<>::_M_destroy                  [C:/MSYS2-32/mingw32/include/c++/10.1.0/bits/basic_string.h:237]
# 4 std::__cxx11::basic_string<>::_M_dispose                  [C:/MSYS2-32/mingw32/include/c++/10.1.0/bits/basic_string.h:232]
# 5 std::__cxx11::basic_string<>::~basic_string               [C:/MSYS2-32/mingw32/include/c++/10.1.0/bits/basic_string.h:658]
# 6 Type::~Type                                               [C:/tests.cpp:5]
# 7 _fu0___ZSt4cout                                           [C:/tests.cpp:27]
# 8 __tmainCRTStartup                                         [D:/mingwbuild/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:335]
# 9 KERNEL32.dll!BaseThreadInitThunk                         +0x18     (0x75306359 <KERNEL32.dll+0x16359>)
Note: @0:00:00.743 in thread 3732
Note: next higher malloc: 0x01750598-0x017505c8
Note: prev lower malloc:  0x01750468-0x0175046b
Note: 0x01750568-0x01750568 overlaps memory 0x01750560-0x01750578 that was freed here:
Note: # 0 replace_operator_delete                              [d:\drmemory_package\common\alloc_replace.c:2975]
Note: # 1 __gnu_cxx::new_allocator<>::deallocate               [C:/MSYS2-32/mingw32/include/c++/10.1.0/ext/new_allocator.h:133]
Note: # 2 std::allocator_traits<>::deallocate                  [C:/MSYS2-32/mingw32/include/c++/10.1.0/bits/allocator.h:187]
Note: # 3 std::_Vector_base<>::_M_deallocate                   [C:/MSYS2-32/mingw32/include/c++/10.1.0/bits/stl_vector.h:354]
Note: # 4 std::vector<>::_M_default_append                     [C:/MSYS2-32/mingw32/include/c++/10.1.0/bits/vector.tcc:675]
Note: # 5 std::vector<>::resize                                [C:/MSYS2-32/mingw32/include/c++/10.1.0/bits/stl_vector.h:940]

===========================================================================
FINAL SUMMARY:

DUPLICATE ERROR COUNTS:

SUPPRESSIONS USED:

ERRORS FOUND:
      1 unique,     1 total unaddressable access(es)
      0 unique,     0 total uninitialized access(es)
      1 unique,     1 total invalid heap argument(s)
      0 unique,     0 total GDI usage error(s)
      0 unique,     0 total handle leak(s)
      0 unique,     0 total warning(s)
      0 unique,     0 total,      0 byte(s) of leak(s)
      0 unique,     0 total,      0 byte(s) of possible leak(s)
ERRORS IGNORED:
      1 potential error(s) (suspected false positives)
         (details: C:\AppData\Roaming\Dr. Memory\DrMemory-CPPTests.exe.14664.000\potential_errors.txt)
      3 unique,     9 total,    154 byte(s) of still-reachable allocation(s)
         (re-run with "-show_reachable" for details)
Details: C:\AppData\Roaming\Dr. Memory\DrMemory-CPPTests.exe.14664.000\results.txt

但我的印象是这一切都很好,因为在调整大小后我没有保留任何指向向量的指针。我不明白什么?

4

1 回答 1

1

当我没有释放任何内存时?

你当然有。您(可能)在这里释放内存:

data.resize(sizeof(Type)*2);
ts[i].~Type();
} // closes main

问题是当向量重新分配内存时,它会将unsigned char元素复制到其他地方。这不适用于Type在该内存中创建的对象,因为Type它不是简单可复制的。

于 2020-06-22T14:07:02.607 回答