c++ - 调整 C++ 类动态数组的大小

标签 c++ arrays class dynamic

我需要调整 m_Array 的大小,它说在添加 11 时在 valgrind 中出现问题。元素 m_Max = 10 m_Len = 10 我可以使用 cstdio、cstdlib、cstring 和 iostream。

/* m_Len is length of array and m_Max is 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++;

这里是涉及到的附加代码:

CAccount
{
 public:
  ~CAccount ( void )
  {
    delete[] m_Trans;
  }
private:
 struct Transaction
 {
   int a;
   const char * b;
   const char * c;
 }
Transaction * m_Trans;


}


CAccount * m_Array;

这就是 valgrind 所说的

我的 friend ...

==2458== Invalid read of size 4
==2458==    at 0x8048D67: CAccount::AddTransaction(int const&, char const*, char const*) (bank_test.cpp:121)
==2458==    by 0x8049645: CBank::Transaction(char const*, char const*, int, char const*) (bank_test.cpp:268)
==2458==    by 0x8049946: main (bank_test.cpp:327)
==2458==  Address 0x434b150 is 0 bytes inside a block of size 4 free'd
==2458==    at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2458==    by 0x8048B0A: CAccount::~CAccount() (bank_test.cpp:92)
==2458==    by 0x804951E: CBank::NewAccount(char const*, int) (bank_test.cpp:254)
==2458==    by 0x804991B: main (bank_test.cpp:323)
==2458== 
==2458== Invalid free() / delete / delete[] / realloc()
==2458==    at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2458==    by 0x8048D9A: CAccount::AddTransaction(int const&, char const*, char const*) (bank_test.cpp:121)
==2458==    by 0x8049645: CBank::Transaction(char const*, char const*, int, char const*) (bank_test.cpp:268)
==2458==    by 0x8049946: main (bank_test.cpp:327)
==2458==  Address 0x434b150 is 0 bytes inside a block of size 4 free'd
==2458==    at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2458==    by 0x8048B0A: CAccount::~CAccount() (bank_test.cpp:92)
==2458==    by 0x804951E: CBank::NewAccount(char const*, int) (bank_test.cpp:254)
==2458==    by 0x804991B: main (bank_test.cpp:323)
==2458== 
==2458== Invalid read of size 4
==2458==    at 0x8048D67: CAccount::AddTransaction(int const&, char const*, char const*) (bank_test.cpp:121)
==2458==    by 0x8049678: CBank::Transaction(char const*, char const*, int, char const*) (bank_test.cpp:269)
==2458==    by 0x8049946: main (bank_test.cpp:327)
==2458==  Address 0x434b188 is 0 bytes inside a block of size 4 free'd
==2458==    at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2458==    by 0x8048B0A: CAccount::~CAccount() (bank_test.cpp:92)
==2458==    by 0x804951E: CBank::NewAccount(char const*, int) (bank_test.cpp:254)
==2458==    by 0x804991B: main (bank_test.cpp:323)
==2458== 
==2458== Invalid free() / delete / delete[] / realloc()
==2458==    at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2458==    by 0x8048D9A: CAccount::AddTransaction(int const&, char const*, char const*) (bank_test.cpp:121)
==2458==    by 0x8049678: CBank::Transaction(char const*, char const*, int, char const*) (bank_test.cpp:269)
==2458==    by 0x8049946: main (bank_test.cpp:327)
==2458==  Address 0x434b188 is 0 bytes inside a block of size 4 free'd
==2458==    at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2458==    by 0x8048B0A: CAccount::~CAccount() (bank_test.cpp:92)
==2458==    by 0x804951E: CBank::NewAccount(char const*, int) (bank_test.cpp:254)
==2458==    by 0x804991B: main (bank_test.cpp:323)
==2458== 

然后它写了另一个 couts 然后它说这个

==2458== Invalid read of size 4
==2458==    at 0x8048AD7: CAccount::~CAccount() (bank_test.cpp:92)
==2458==    by 0x804922E: CBank::~CBank() (bank_test.cpp:224)
==2458==    by 0x80499F0: main (bank_test.cpp:381)
==2458==  Address 0x434b348 is 0 bytes inside a block of size 4 free'd
==2458==    at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2458==    by 0x8048B0A: CAccount::~CAccount() (bank_test.cpp:92)
==2458==    by 0x804951E: CBank::NewAccount(char const*, int) (bank_test.cpp:254)
==2458==    by 0x804991B: main (bank_test.cpp:323)
==2458== 
==2458== Invalid free() / delete / delete[] / realloc()
==2458==    at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2458==    by 0x8048B0A: CAccount::~CAccount() (bank_test.cpp:92)
==2458==    by 0x804922E: CBank::~CBank() (bank_test.cpp:224)
==2458==    by 0x80499F0: main (bank_test.cpp:381)
==2458==  Address 0x434b348 is 0 bytes inside a block of size 4 free'd
==2458==    at 0x402B598: operator delete[](void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==2458==    by 0x8048B0A: CAccount::~CAccount() (bank_test.cpp:92)
==2458==    by 0x804951E: CBank::NewAccount(char const*, int) (bank_test.cpp:254)
==2458==    by 0x804991B: main (bank_test.cpp:323)
==2458== 
==2458== 
==2458== HEAP SUMMARY:
==2458==     in use at exit: 0 bytes in 0 blocks
==2458==   total heap usage: 17 allocs, 27 frees, 1,268 bytes allocated
==2458== 
==2458== All heap blocks were freed -- no leaks are possible
==2458== 
==2458== For counts of detected and suppressed errors, rerun with: -v
==2458== ERROR SUMMARY: 20 errors from 6 contexts (suppressed: 0 from 0)

最佳答案

是这样的:

CAccount * tmp = new CAccount[m_Max];

您创建了 20 个新对象 CAccount。

memcpy ( tmp, m_Array, m_Len * sizeof(CAccount));

您将 10 个旧对象 CAccount 的内容 memcpy 到新数组。

问题是,由于您只使用了 memcpy 而没有处理数据所有权的复制构造函数,对象的新旧版本都指向相同的 m_Trans数据。

一旦调用 delete[] m_Array;,旧对象的析构函数就会被调用,它们会删除 m_Trans

删除[] m_Trans;

现在新对象指向已被删除的 m_Trans 数据,因此访问指针将导致未定义的行为。

解决这个问题最干净的方法是使用

memcpy ( tmp, m_Array, m_Len * sizeof(CAccount));

std::copy(m_Array, m_Array + m_Len, tmp)

这会在新对象上调用 opreator=,因此您也需要正确地进行设置:

CAccount
{
public:
  CAccount::CAccount(const CAccount& account)
  : m_trans(<initialisation code here>)
{
  <Copy the data from the account>
}

这个解决方案是最干净但不是最理想的,因为您正在复制数据,您可以只切换数据的所有者,但如果您不追求性能,这会更好。

关于c++ - 调整 C++ 类动态数组的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23033331/

相关文章:

C++ 将 32 位整数复制到字节数组

c++ - 不同类别的内存

java - 如何拆分 ArrayList 并将数据存储到 android 中的 String 数组中?

javascript - 如何在 javascript 中对这个对象数组进行排序?

c++ - 查看固定长度数组之间有多少字节相等的最快方法

c++ - 使用移动赋值从算术运算符重载返回 const 值

未引用类的 C++ 静态变量

javascript - 如何从名称中获取 javascript 类

javascript - ReactJS:从基础组件访问上下文

python - 比较python类中的变量