问题描述
我写了一小段这样的代码:
I wrote a small piece of code like this:
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报告这样的内存错误:
When T is [int] or [foo], everything works fine. But using [std::string] as T causes valgrind to report memory errors like this:
==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&中都具有malloc/freedtor吗?
why only [std::string] leads to memory problem while [foo] also has malloc/free in both ctor & dtor ?
我正在使用g ++ 6.2.1和valgrind 3.12.0
I'm using g++ 6.2.1 and valgrind 3.12.0
推荐答案
malloc()
, free()
和 realloc()
是C库函数,对C ++类,它们的构造函数和析构函数完全一无所知.
malloc()
, free()
, and realloc()
are C library functions, that know absolutely nothing about C++ classes, their constructors, and destructors.
您正在将 malloc()
与位置 new
一起使用,以使用 malloc
-构造 std :: string
-ed记忆.很好.
You are using malloc()
with placement new
to construct a std::string
using malloc
-ed memory. This is fine.
但是,您正在使用 realloc()
重新分配已分配的内存.
But then, you're using realloc()
to reallocate the allocated memory.
必须使用相应对象的复制/移动构造函数来完成在内存中复制/移动C ++对象的操作.不能使用 realloc()
复制/移动内存中的C ++对象.
Copying/moving C++ objects in memory must be done using the respective objects' copy/move constructors. Copying/moving C++ objects in memory cannot be done with realloc()
.
执行此操作的唯一方法是 malloc()
一个新的内存块,使用放置 new
调用对象的copy/move构造函数以进行复制/将它们移到新的内存块中,最后调用旧内存块中对象的析构函数,然后可以对其进行 free()
-ed.
The only way to do this is to malloc()
a new memory block, use placement new
to invoke the objects' copy/move constructors in order to copy/move them into the new memory block, and finally invoke the destructor of the objects in the old memory block, after which it can be free()
-ed.
这篇关于在std :: string上使用malloc/realloc/free时出现c ++内存错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!