gpt4 book ai didi

c++ - 查找C++内存泄漏

转载 作者:行者123 更新时间:2023-12-03 07:22:42 25 4
gpt4 key购买 nike

我目前正在研究Vector类。我需要使用某些概念,例如模板等。在大多数情况下,我已经完成了整个项目,但内存泄漏使我无法定位。
我正在使用macOS Catalina,并且尝试安装Valgrind,但似乎无法正常工作。这本身就是另一个问题。内存泄漏在哪里?检测macOS Catalina用户内存泄漏在哪里的简便方法是什么?
我也在使用VS Code。
头文件
注意:ContainerIfc是一个抽象类,所有需要理解的方法都在下面实现。


#ifndef PROJ7_MYVECTOR
#define PROJ7_MYVECTOR

#include "proj7-ContainerIfc.h"

template <class T>
class MyVector : public ContainerIfc<T>
{
public:
/**
* MyVector
*
* This is the default constructor that sets size equal
* to 0 and capacity to 10.
*
* Parameters: none
*
* Output:
* return: none
* reference parameters: none
* stream: none
*/
MyVector();

/**
* ~MyVector
*
* This is the destructor that deletes memory
*
* Parameters: none
*
* Output:
* return: none
* reference parameters: none
* stream: none
*/
~MyVector();

/**
* MyVector
*
* This is the copy constructor
*
* Parameters:
* v: the object that you want to copy over
*
* Output:
* return: none
* reference parameters: none
* stream: none
*/
MyVector(const MyVector &);

/**
* = operator
*
* This is the overloaded assignment operator
*
* Parameters:
* v: the object that you want to copy over
*
* Output:
* return: none
* reference parameters: none
* stream: none
*/
MyVector<T> &operator=(const MyVector &);

/**
* pushFront
*
* Prepends a value to the array
*
* Parameters:
* e: The value that you want to prepend
*
* Output:
* return: none
* reference parameters: none
* stream: none
*/
MyVector<T> &pushFront(T);

/**
* pushBack
*
* Appends a vlue to the array
*
* Parameters:
* e: The value that you want to append
*
* Output:
* return: none
* reference parameters: none
* stream: none
*/
MyVector<T> &pushBack(T);

/**
* popFront
*
* Removes the first index of the array and shifts all elements leftward
*
* Parameters:
* e: The value that was removed
*
* Output:
* return: none
* reference parameters: e
* stream: none
*/
MyVector<T> &popFront(T &);

/**
* popBack
*
* Removes the last index of the array
*
* Parameters:
* e: The value that was removed
*
* Output:
* return: none
* reference parameters: none
* stream: none
*/
MyVector<T> &popBack(T &);

/**
* front
*
* Returns the first element of the array
*
* Parameters: none
*
* Output:
* return: Copy of the first data item in the MyVector
* reference parameters: none
* stream: none
*/
T front();

/**
* back
*
* Returns the last element of the array
*
* Parameters: none
*
* Output:
* return: Returns a copy of the last data item in MyVector
* reference parameters: none
* stream: none
*/
T back();

/**
* [] operator
*
* Returns a reference to data element n in MyVector
*
* Parameters:
* n: index of item to return
*
* Output:
* return: Returns a reference to data element n in MyVector
* reference parameters: none
* stream: none
*/
T &operator[](int);

/**
* getSize
*
* Returns size of MyVector array
*
* Parameters: none
*
* Output:
* return: an integer value representing the number of elements in the list
* reference parameters: none
* stream: none
*/
int getSize();

/**
* isEmpty
*
* Returns state information about the list
*
* Parameters: none
*
* Output:
* return: Returns state information about the list
* reference parameters: none
* stream: none
*/
bool isEmpty();

/**
* erase
*
* Erases a vector
*
* Parameters: none
*
* Output:
* return: none
* reference parameters: none
* stream: none
*/
void erase();

private:
T *data;
int size;
int capacity;

/**
* grow
*
* Increases the capacity of data by doubling the previous value and allocating
* the appropriate memory for data
*
* Parameters: none
*
* Output:
* return: none
* reference parameters: none
* stream: none
*/
void grow();

/**
* shiftRight
*
* Shifts all values in the array one space to the right
*
* Parameters: none
*
* Output:
* return: none
* reference parameters: none
* stream: none
*/
void shiftRight();

/**
* shiftLeft
*
* Shifts all values in the array one space to the left
*
* Parameters: none
*
* Output:
* return: none
* reference parameters: none
* stream: none
*/
void shiftLeft();
};

template <class T>
MyVector<T>::MyVector()
{
this->size = 0;
this->capacity = 10;
this->data = new T[this->capacity];
}

template <class T>
MyVector<T>::~MyVector()
{
delete[] this->data;
}

template <class T>
MyVector<T>::MyVector(const MyVector &v)
{
this->size = v.size;
this->capacity = v.capacity;
this->data = new T[this->capacity];

// Copy each array item over
for (int i = 0; i < this->size; i++)
{
this->data[i] = v.data[i];
}
}

template <class T>
MyVector<T> &MyVector<T>::operator=(const MyVector &v)
{
this->size = v.size;
this->capacity = v.capacity;
this->data = new T[this->capacity];

// Copy each array item over
for (int i = 0; i < this->size; i++)
{
this->data[i] = v.data[i];
}

return *this;
}

template <class T>
MyVector<T> &MyVector<T>::pushFront(T e)
{
// Resize if necessary
if (this->size == this->capacity)
{
this->grow();
}

// Shift elements to the right
this->shiftRight();

// Add new value to first index of array
this->data[0] = e;

// Increment size
this->size++;

return *this;
}

template <class T>
MyVector<T> &MyVector<T>::pushBack(T e)
{
// Resize if necessary
if (this->size == this->capacity)
{
this->grow();
}

// Add value to array
this->data[this->size] = e;

// Increment size
this->size++;

return *this;
}

template <class T>
MyVector<T> &MyVector<T>::popFront(T &e)
{
// Throw BADINDEX if empty
if (this->size <= 0)
{
throw BADINDEX();
}

// Set e equal to the first value
e = this->front();

// Shift elements to the left removing the first index
this->shiftLeft();

// Decrement size
this->size--;

return *this;
}

template <class T>
MyVector<T> &MyVector<T>::popBack(T &e)
{
// Throw BADINDEX if empty
if (this->size <= 0)
{
throw BADINDEX();
}
// Set e equal to the last value
e = this->back();

// Remove last element by creating new array and copying values
T *temp = new T[this->capacity];

// Ignore last element and copy all values
for (int i = 0; i < this->size - 1; i++)
{
temp[i] = this->data[i];
}

// Deallocate current array
delete[] this->data;

// Allocate new temp array
this->data = temp;

// Decrement size
this->size--;

return *this;
}

template <class T>
T MyVector<T>::front()
{
// Throw BADINDEX if empty
if (this->size <= 0)
{
throw BADINDEX();
}

return this->data[0];
}

template <class T>
T MyVector<T>::back()
{
// Throw BADINDEX if empty
if (this->size <= 0)
{
throw BADINDEX();
}

return this->data[this->size - 1];
}

template <class T>
T &MyVector<T>::operator[](int n)
{
// Throw BADINDEX if n doesn't exist
if (n > this->size - 1)
{
throw BADINDEX();
}

return this->data[n];
}

template <class T>
int MyVector<T>::getSize()
{
return this->size;
}

template <class T>
bool MyVector<T>::isEmpty()
{
bool isEmpty = true;

// Check if size is greater than 0
if (this->size > 0)
{
isEmpty = true;
}

return isEmpty;
}

template <class T>
void MyVector<T>::erase()
{
// Erase vector by deallocating and allocating a new one
// Reset size & capacity
this->size = 0;
this->capacity = 10;

// Create new empty array
T *temp = new T[this->capacity];

// Delete old array
delete[] this->data;

// Set current array to new array
this->data = temp;
}

template <class T>
void MyVector<T>::grow()
{
// Double capacity as instructions say
this->capacity *= 2;
T *temp = new T[this->capacity];

// Copy each array item over
for (int i = 0; i < this->size; i++)
{
temp[i] = this->data[i];
}

// Deallocate current array
delete[] this->data;

// Allocate new temp array
this->data = temp;
}

template <class T>
void MyVector<T>::shiftRight()
{
// Create a new array
T *temp = new T[this->capacity];

// Copy values over shifting one to the right
for (int i = 1; i < this->size + 1; i++)
{
temp[i] = this->data[i - 1];
}

// Deallocate current array
delete[] this->data;

// Allocate new temp array
this->data = temp;
}

template <class T>
void MyVector<T>::shiftLeft()
{
// Create new array
T *temp = new T[this->capacity];

for (int i = 1; i < this->size; i++)
{
temp[i - 1] = this->data[i];
}

// Deallocate current array
delete[] this->data;

// Allocate new temp array
this->data = temp;
}

#endif
测试文件

#include <iostream>

#include "proj7-MyVector.h"

using namespace std;

int main()
{
cout << "MyVector Test" << endl;
cout << "Testing all functions using int MyVector, string MyVector, and double MyVector" << endl;

cout << endl;

cout << "Testing Default Constructor: ";
MyVector<int> intVector;
MyVector<string> stringVector;
MyVector<double> doubleVector;
cout << "Pass" << endl;

cout << "Testing pushFront: ";
intVector.pushFront(1);
stringVector.pushFront("test");
doubleVector.pushBack(1.32);
cout << "Pass" << endl;

cout << "Testing [] operator: ";
if (intVector[0] == 1 && stringVector[0] == "test" && doubleVector[0] == 1.32)
{
cout << "Pass" << endl;
}
else
{
cout << "Fail" << endl;
}

cout << "Testing pushBack: ";
intVector.pushBack(22);
stringVector.pushBack("hello");
doubleVector.pushBack(8.21);
cout << "Pass" << endl;

cout << "Testing back: ";
if (intVector.back() == 22 && stringVector.back() == "hello" && doubleVector.back() == 8.21)
{
cout << "Pass" << endl;
}
else
{
cout << "Fail" << endl;
}

cout << "Testing front: ";
if (intVector.front() == 1 && stringVector.front() == "test" && doubleVector.front() == 1.32)
{
cout << "Pass" << endl;
}
else
{
cout << "Fail" << endl;
}

cout << "Testing popFront: ";
int removedInt;
string removedString;
double removedDouble;
intVector.popFront(removedInt);
stringVector.popFront(removedString);
doubleVector.popFront(removedDouble);

if (removedInt == 1 && removedString == "test" && removedDouble == 1.32)
{
cout << "Pass" << endl;
}
else
{
cout << "Fail" << endl;
}

cout << "Testing getSize: ";
if (intVector.getSize() == 1 && stringVector.getSize() == 1 && doubleVector.getSize() == 1)
{
cout << "Pass" << endl;
}
else
{
cout << "Fail" << endl;
}

cout << "Testing popBack: ";
intVector.popBack(removedInt);
stringVector.popBack(removedString);
doubleVector.popBack(removedDouble);

if (removedInt == 22 && removedString == "hello" && removedDouble == 8.21)
{
cout << "Pass" << endl;
}
else
{
cout << "Fail" << endl;
}

cout << "Testing isEmpty: ";
if (intVector.isEmpty() && stringVector.isEmpty() && doubleVector.isEmpty())
{
cout << "Pass" << endl;
}
else
{
cout << "Fail" << endl;
}

cout << "Testing = operator: ";
for (int i = 0; i < 10; i++)
{
intVector.pushBack(i);
stringVector.pushBack("a");
doubleVector.pushBack(2.5);
}

MyVector<int> intVector2;
MyVector<string> stringVector2;
MyVector<double> doubleVector2;

intVector2 = intVector;
stringVector2 = stringVector;
doubleVector2 = doubleVector;

if (intVector2.front() == 0 && stringVector2.front() == "a" && doubleVector2.front() == 2.5)
{
cout << "Pass" << endl;
}
else
{
cout << "Fail" << endl;
}

cout << "Testing copy constructor: ";
MyVector<int> intVector3(intVector2);
MyVector<string> stringVector3(stringVector2);
MyVector<double> doubleVector3(doubleVector2);

if (intVector2.front() == 0 && stringVector2.front() == "a" && doubleVector2.front() == 2.5)
{
cout << "Pass" << endl;
}
else
{
cout << "Fail" << endl;
}

cout << "Testing erase: ";
intVector3.erase();
stringVector3.erase();
doubleVector3.erase();

if (intVector3.isEmpty() && stringVector3.isEmpty() && doubleVector3.isEmpty())
{
cout << "Pass" << endl;
}
else
{
cout << "Fail" << endl;
}

cout << "If all of the above pass, grow(), shiftRight() and shiftLeft() are assumed passing." << endl;


return 0;
}

最佳答案

template <class T>
MyVector<T> &MyVector<T>::operator=(const MyVector &v)
{
this->size = v.size;
this->capacity = v.capacity;
this->data = new T[this->capacity];
先前分配的 this->data在此处泄漏。已经分配了。
此外,大多数类方法都不需要 new一个新的 temp缓冲区,将 data复制到它,然后 delete旧的 data,然后将其替换为新分配的 temp缓冲区。
这似乎是不必要的工作,因为看起来大多数这些操作都可以就地完成。此外,似乎其中至少有一个错误,在某些情况下会导致内存损坏。在您的 shiftRight中:
for (int i = 1; i < this->size + 1; i++)
{
temp[i] = this->data[i - 1];
}
这将为 temp[this->size]分配一些内容。如果 this->size恰好等于 this->capacity,因为 temp的大小被分配为 this->capacity,这将导致 rather nasty demon flying out of your nose,因为 temp[this->size]不存在。

关于c++ - 查找C++内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64627167/

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