gpt4 book ai didi

c++ - c++ : valgrind leak 中的动态数组

转载 作者:太空狗 更新时间:2023-10-29 21:11:24 24 4
gpt4 key购买 nike

我正在尝试用 C++ 实现一个动态数组。一旦它变满,它的大小就会加倍并复制到双倍大小的数组中。它看起来不错,但 Valgrind 说我有泄漏。我应该说我不允许使用任何 C++ STL 结构——这就是我使用 new[] 和 delete[] 运算符的原因。

这是我的代码:

template<class T>
class DynamicArray
{

int size;
int numOfElements;
T* arr;

public:
DynamicArray(int size) :
size(size), numOfElements(0)
{
arr = new T[size];
}
;

int getSize()
{
return size;
}

int getNumberOfElements()
{
return numOfElements;
}

void insert(T element)
{
arr[numOfElements++] = element;
if (numOfElements == size)
{
T* extended_array = new T[size * 2];
for (int i = 0; i < numOfElements; i++)
{
extended_array[i] = arr[i];
}
delete[] arr;
arr = extended_array;
size = size * 2;
}
}

T& operator[](int i)
{
if (!((i >= 0) && (i < size)))
throw arrayOutOfBoundsException();
return arr[i];
}

~DynamicArray()
{
delete[] arr;
}

class arrayOutOfBoundsException: std::exception
{
};
};

我的主要程序是:

using std::cout;
using std::endl;

void printIntArray(DynamicArray<int> arr){
cout << "size: " << arr.getSize() << "; " << "numOfElemnts: " << arr.getNumberOfElements() << endl;
cout << "array: ";
for(int i=0; i<arr.getNumberOfElements(); i++){
cout << " " << arr[i];
}
cout << endl << endl;
}


int main() {

DynamicArray<int> arr(5);
printIntArray(arr);



arr.insert(1);
arr.insert(2);
arr.insert(3);
printIntArray(arr);

arr.insert(4);
printIntArray(arr);

arr.insert(5);
printIntArray(arr);

arr.insert(6);
printIntArray(arr);

arr.insert(7);
arr.insert(8);
arr.insert(9);
printIntArray(arr);

arr.insert(16);
printIntArray(arr);

arr[9] = 901;
arr[0] = 101;
printIntArray(arr);

**valgrind 向我展示了这个错误——当析构函数被编译为注释时:

==3954== 80 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3954== at 0x4A07192: operator new[](unsigned long) (vg_replace_malloc.c:363)
==3954== by 0x40103E: DynamicArray<int>::insert(int) (DynamicArray.h:41)
==3954== by 0x400DBC: main (main.cpp:44)**

谁能告诉我我做错了什么?我在滥用“delete[]”吗?还是析构函数?

谢谢

最佳答案

提问者描述的行为是不可能的或

when the destructor is compiled as comment:

表示析构函数已被注释掉,这会导致泄漏。这已在评论中得到证实。如果没有析构函数,最后的分配将永远不会被丢弃。

提问者的真正问题是违反三次规则。

简短的版本是这样的:

如果一个类需要用户定义的复制构造函数、赋值运算符或析构函数,它几乎总是需要这三个。

更多相关信息:What is The Rule of Three?

在这种情况下,

void printIntArray(DynamicArray<int> arr)

按值接受 arr。这意味着 arr 是传入值的拷贝。在没有自定义复制构造函数的情况下,printIntArray 中的 arr 将指向与源相同的分配。拷贝将在 printIntArray 结束时被销毁,析构函数将删除分配,使源指向无效内存,所以...

DynamicArray<int> arr(5); // allocated storage inside arr
printIntArray(arr); // made a copy of arr that points to same storage.
// Storage freed when copy destroyed

arr.insert(1); // invokes undefined behaviour writing into invalid memory
arr.insert(2); // same
arr.insert(3); // same
printIntArray(arr); // copies arr again. This copy is pointing to the same invalid memory
// and will try to free the allocation a second time when the
// copy is destroyed

程序几乎肯定会在这里崩溃,从而无法从用户代码中泄漏。但是因为程序崩溃了,Crom 只知道运行时使用了哪些幕后结构没有正确收起来。

无论发生什么,截至

arr.insert(1);

程序深入Undefined Behaviour在那之后发生的一切都是任何人的猜测。内存泄漏是您最不担心的事情。

修复:满足三规则

实现复制构造函数和赋值运算符(We'll ignore the Rule of Five for now.)

你可以改变

void printIntArray(DynamicArray<int> arr)

通过引用传递

void printIntArray(DynamicArray<int> & arr)

然后

DynamicArray(const DynamicArray &) = delete;
DynamicArray& operator=(const DynamicArray &) = delete;

并禁用所有复制,但这似乎有点严苛。

改为lets use Copy and Swap因为它简单易懂。请注意,它也可能效率低下,因此它并不总是正确的工具。这里正好符合我们的要求。

DynamicArray(const DynamicArray & src)  :
size(src.size), numOfElements(src.numOfElements), arr(new T[size])
{
for (int i = 0; i < numOfElements; i++)
{
arr[i] = src.arr[i];
}
}


DynamicArray& operator=(const DynamicArray src)
{
std::swap(size, src.size);
std::swap(numOfElements, src.numOfElements);
std::swap(arr, src.arr);
return *this;
}

因为谁想要复制他们不需要,我们仍然会

void printIntArray(DynamicArray<int> & arr)

一旦我们完成了复制构造函数正常工作的测试。

关于c++ - c++ : valgrind leak 中的动态数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50731344/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com