Resizing dynamic array of Class C++ -
i need resize m_array , saying problems in valgrind when adding 11. element m_max = 10 m_len = 10 allowed use cstdio,cstdlib,cstring , iostream.
/* m_len length of array , m_max maximal length */ resizing in caccount::newaccount if ( m_len >= m_max ) { if (m_max == 0) m_max = 5; m_max *= 2; caccount * tmp = new caccount[m_max]; memcpy ( tmp, m_array, m_len * sizeof(caccount)); delete[] m_array; m_array = tmp; } m_array[m_len] = x; m_len++;
here aditional code involved in this:
caccount { public: ~caccount ( void ) { delete[] m_trans; } private: struct transaction { int a; const char * b; const char * c; } transaction * m_trans; } caccount * m_array;
this valgrind says
my couts...
==2458== invalid read of size 4 ==2458== @ 0x8048d67: caccount::addtransaction(int const&, char const*, char const*) (bank_test.cpp:121) ==2458== 0x8049645: cbank::transaction(char const*, char const*, int, char const*) (bank_test.cpp:268) ==2458== 0x8049946: main (bank_test.cpp:327) ==2458== address 0x434b150 0 bytes inside block of size 4 free'd ==2458== @ 0x402b598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==2458== 0x8048b0a: caccount::~caccount() (bank_test.cpp:92) ==2458== 0x804951e: cbank::newaccount(char const*, int) (bank_test.cpp:254) ==2458== 0x804991b: main (bank_test.cpp:323) ==2458== ==2458== invalid free() / delete / delete[] / realloc() ==2458== @ 0x402b598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==2458== 0x8048d9a: caccount::addtransaction(int const&, char const*, char const*) (bank_test.cpp:121) ==2458== 0x8049645: cbank::transaction(char const*, char const*, int, char const*) (bank_test.cpp:268) ==2458== 0x8049946: main (bank_test.cpp:327) ==2458== address 0x434b150 0 bytes inside block of size 4 free'd ==2458== @ 0x402b598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==2458== 0x8048b0a: caccount::~caccount() (bank_test.cpp:92) ==2458== 0x804951e: cbank::newaccount(char const*, int) (bank_test.cpp:254) ==2458== 0x804991b: main (bank_test.cpp:323) ==2458== ==2458== invalid read of size 4 ==2458== @ 0x8048d67: caccount::addtransaction(int const&, char const*, char const*) (bank_test.cpp:121) ==2458== 0x8049678: cbank::transaction(char const*, char const*, int, char const*) (bank_test.cpp:269) ==2458== 0x8049946: main (bank_test.cpp:327) ==2458== address 0x434b188 0 bytes inside block of size 4 free'd ==2458== @ 0x402b598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==2458== 0x8048b0a: caccount::~caccount() (bank_test.cpp:92) ==2458== 0x804951e: cbank::newaccount(char const*, int) (bank_test.cpp:254) ==2458== 0x804991b: main (bank_test.cpp:323) ==2458== ==2458== invalid free() / delete / delete[] / realloc() ==2458== @ 0x402b598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==2458== 0x8048d9a: caccount::addtransaction(int const&, char const*, char const*) (bank_test.cpp:121) ==2458== 0x8049678: cbank::transaction(char const*, char const*, int, char const*) (bank_test.cpp:269) ==2458== 0x8049946: main (bank_test.cpp:327) ==2458== address 0x434b188 0 bytes inside block of size 4 free'd ==2458== @ 0x402b598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==2458== 0x8048b0a: caccount::~caccount() (bank_test.cpp:92) ==2458== 0x804951e: cbank::newaccount(char const*, int) (bank_test.cpp:254) ==2458== 0x804991b: main (bank_test.cpp:323) ==2458==
then writes couts , says this
==2458== invalid read of size 4 ==2458== @ 0x8048ad7: caccount::~caccount() (bank_test.cpp:92) ==2458== 0x804922e: cbank::~cbank() (bank_test.cpp:224) ==2458== 0x80499f0: main (bank_test.cpp:381) ==2458== address 0x434b348 0 bytes inside block of size 4 free'd ==2458== @ 0x402b598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==2458== 0x8048b0a: caccount::~caccount() (bank_test.cpp:92) ==2458== 0x804951e: cbank::newaccount(char const*, int) (bank_test.cpp:254) ==2458== 0x804991b: main (bank_test.cpp:323) ==2458== ==2458== invalid free() / delete / delete[] / realloc() ==2458== @ 0x402b598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==2458== 0x8048b0a: caccount::~caccount() (bank_test.cpp:92) ==2458== 0x804922e: cbank::~cbank() (bank_test.cpp:224) ==2458== 0x80499f0: main (bank_test.cpp:381) ==2458== address 0x434b348 0 bytes inside block of size 4 free'd ==2458== @ 0x402b598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==2458== 0x8048b0a: caccount::~caccount() (bank_test.cpp:92) ==2458== 0x804951e: cbank::newaccount(char const*, int) (bank_test.cpp:254) ==2458== 0x804991b: main (bank_test.cpp:323) ==2458== ==2458== ==2458== heap summary: ==2458== in use @ exit: 0 bytes in 0 blocks ==2458== total heap usage: 17 allocs, 27 frees, 1,268 bytes allocated ==2458== ==2458== heap blocks freed -- no leaks possible ==2458== ==2458== counts of detected , suppressed errors, rerun with: -v ==2458== error summary: 20 errors 6 contexts (suppressed: 0 0)
this happens:
caccount * tmp = new caccount[m_max];
you created 20 new objects caccount.
memcpy ( tmp, m_array, m_len * sizeof(caccount));
you memcpy-ied content of 10 old objects caccount new array.
the problem is, used memcpy , no copy constructor take care of ownership of data, both new , old versions of objects pointing same m_trans
data.
once call delete[] m_array;
destructors on old objects called, , remove m_trans
delete[] m_trans;
now new objects pointing m_trans
data removed accessing pointer lead undefined behavior.
the cleanest way solve use instead of
memcpy ( tmp, m_array, m_len * sizeof(caccount));
do
std::copy(m_array, m_array + m_len, tmp)
this calls opreator= on new objects, need make correctly well:
caccount { public: caccount::caccount(const caccount& account) : m_trans(<initialisation code here>) { <copy data account> }
this solution cleanest sub-optimal, copying data, switch owner of data, if not shooting performance better.
Comments
Post a Comment