【问题标题】:c++ memory error when using malloc/realloc/free on std::stringc++ 在 std::string 上使用 malloc/realloc/free 时出现内存错误
【发布时间】:2017-03-18 23:27:24
【问题描述】:

我这样写了一小段代码:

template <class T>
void
test()
{
    T* ptr = nullptr;

    ptr = (T*)malloc(1 * sizeof(T));

    new ((void*)ptr) T(T());

    ptr = (T*)realloc(ptr, 2 * sizeof(T));

    new ((void*)(ptr + 1)) T(T());

    (ptr)->~T();
    (ptr + 1)->~T();

    free(ptr);
}

struct foo
{
    foo() : ptr(malloc(10)) {}
    ~foo() { free(ptr); } 
    void* ptr;
};

int
main()
{ 
    test<int>(); // this is ok
    test<foo>(); // this is ok
    test<std::string>(); // memory error :(

    return 0;
}; 

当 T 为 [int] 或 [foo] 时,一切正常。但是使用 [std::string] 作为 T 会导致 valgrind 报告这样的内存错误:

==18184== Memcheck, a memory error detector
==18184== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==18184== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==18184== Command: ./a.out
==18184== 
==18184== Invalid free() / delete / delete[] / realloc()
==18184==    at 0x4C2C20A: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18184==    by 0x401074: void test<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >() (tmp.cpp:26)
==18184==    by 0x400CFC: main (tmp.cpp:44)
==18184==  Address 0x5a89e70 is 16 bytes inside a block of size 32 free'd
==18184==    at 0x4C2CC37: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18184==    by 0x401042: void test<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >() (tmp.cpp:22)
==18184==    by 0x400CFC: main (tmp.cpp:44)
==18184==  Block was alloc'd at
==18184==    at 0x4C2AB8D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18184==    by 0x40100F: void test<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >() (tmp.cpp:18)
==18184==    by 0x400CFC: main (tmp.cpp:44)
==18184== 
==18184== 
==18184== HEAP SUMMARY:
==18184==     in use at exit: 0 bytes in 0 blocks
==18184==   total heap usage: 9 allocs, 10 frees, 72,856 bytes allocated
==18184== 
==18184== All heap blocks were freed -- no leaks are possible
==18184== 
==18184== For counts of detected and suppressed errors, rerun with: -v
==18184== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

为什么只有 [std::string] 会导致内存问题,而 [foo] 在 ctor 和 dtor 中也有 malloc/free ?

我正在使用 g++ 6.2.1 和 valgrind 3.12.0

【问题讨论】:

    标签: c++ string memory valgrind realloc


    【解决方案1】:

    realloc 与非 POD 类型不兼容。

    因为它可以移动内存中的东西,而移动的对象不知道它。

    【讨论】:

      【解决方案2】:

      malloc()free()realloc() 是 C 库函数,它们对 C++ 类及其构造函数和析构函数一无所知。

      您正在使用 malloc() 和位置 new 来构造 std::string 使用 malloc-ed 内存。这很好。

      但是,您正在使用realloc() 重新分配分配的内存。

      在内存中复制/移动 C++ 对象必须使用相应对象的复制/移动构造函数来完成。 realloc() 无法在内存中复制/移动 C++ 对象。

      这样做的唯一方法是 malloc() 一个新的内存块,使用放置 new 调用对象的复制/移动构造函数以便将它们复制/移动到新的内存块中,最后调用旧内存块中对象的析构函数,之后可以是free()-ed。

      【讨论】:

        猜你喜欢
        • 2011-11-28
        • 2021-06-28
        • 2017-07-20
        • 2021-03-04
        • 1970-01-01
        • 2021-03-26
        • 2010-09-15
        • 2010-11-06
        • 2019-08-01
        相关资源
        最近更新 更多