2016-11-05 3 views
0

Я написал небольшой кусок кода, как это:C++ ошибка памяти при использовании таНос/перераспределить/бесплатно на станд :: строка

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; 
}; 

Когда Т [INT] или [Foo], все работает отлично. Но с помощью [стд :: строка], как 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) 

почему только [станд :: строка] приводит к проблеме памяти в то время как [Foo] также имеет таНос/бесплатно и в CTOR & dtor?

Я использую г ++ 6.2.1 и Valgrind 3.12.0

ответ

3

malloc(), free() и realloc() являются библиотечные функции С, что абсолютно ничего не известно о классах C++, их конструкторам и деструкторов.

Вы используете malloc() с размещением new для построения std::string с использованием памяти malloc. Это отлично.

Но тогда вы используете realloc() для перераспределения выделенной памяти.

Копирование/перемещение объектов C++ в памяти должно выполняться с использованием конструкторов копирования/перемещения соответствующих объектов. Копирование/перемещение объектов C++ в памяти невозможно с помощью realloc().

Единственный способ сделать это состоит в malloc() нового блок памяти, использование размещение new для вызова копировать/перемещать конструкторы Объектов, чтобы скопировать/переместить их в новый блок памяти, и, наконец, ссылаться на деструктор объекты в старом блоке памяти, после чего он может быть free() -ed.

2

realloc не совместим с типами, отличными от POD.

Потому что он может перемещать вещи в памяти, если перемещенные объекты не знают об этом.