I'm writing a basic List class. It's backed by an array, not a vector, because we aren't allowed to use vectors.
I seem to be running into heap corruption issues when I call delete[] on my internal backing array.
template <typename T>
void List<T>::Remove( int elementIndex )
{
// Here, I'm creating a new array of one less size to copy all elements over
T* newArray = new T[Count - 1];
bool skippedElement = false;
for (int i = 0; i < Count; i++)
{
if (i == elementIndex)
skippedElement = true;
newArray[i] = array[ skippedElement ? i + 1 : i ];
}
delete[] array; // Heap corruption! See below for definition of array
array = newArray;
Count--;
Capacity--;
}
List.h
class List
{
...
private:
T* array;
...
template <typename T>
List<T>::List( void )
{
array = new T[1];
}
template <typename T>
List<T>::~List( void )
{
delete[] array;
}
}
Does anybody know why this is occuring?
According to this useful post, it says:
"Most heap corruption is caused by (A) calling delete too many times (B) calling the wrong form of delete, or (C) accessing a heap-allocated array out of bounds."
I'm just not sure whether A, B, or/and C are true. Am I calling delete after it's already deleted? I don't think so. I also think I'm calling the right form of delete: delete with brackets. And I sure hope not C.
In your for loop you are iterating Count no of times. But your new array can hold only Count - 1 number of elements. This leads to a heap corruption.
Related
The following function appears in the OctoMap code:
class AbstractOcTreeNode {}; -> They declare an empty class
AbstractOcTreeNode** children; -> This is declared in the OcTreeDataNode class header file
template <typename T>
void OcTreeDataNode<T>::allocChildren() {
children = new AbstractOcTreeNode*[8];
for (unsigned int i=0; i<8; i++) {
children[i] = NULL;
}
}
Wouldn't this cause memory leak? Shouldn't it be:
template <typename T>
void OcTreeDataNode<T>::allocChildren() {
children = new AbstractOcTreeNode*[8];
for (unsigned int i=0; i<8; i++) {
delete children[i];
children[i] = NULL;
}
}
What am I missing? Thanks for the help!
You'd want to delete the entire array, not each of the individual array elements
template <typename T>
void OcTreeDataNode<T>::allocChildren() {
children = new AbstractOcTreeNode*[8];
for (unsigned int i=0; i<8; i++) {
children[i] = NULL;
}
// .... later
delete[] children ;
}
You must always match a new with a delete, and a new[] with a delete[], without mixing them.
For completeness (I'm guessing at the context) since the name of the function is allocChildren I assume it is their intention to new[] the array and not cleanup the memory, yet. Hopefully there would be a matching deallocChildren that would delete[] this memory later.
What is the sense to allocate memory and at once to delete it?
template <typename T>
void OcTreeDataNode<T>::allocChildren() {
children = new AbstractOcTreeNode*[8];
for (unsigned int i=0; i<8; i++) {
delete children[i];
children[i] = NULL;
}
}
The function above does not make sense.
Pay attention to that an empty class has a non-zero size.
And there is allocated an array of pointers to an empty class. Objects of the class are not allocated in this function.
In this function
template <typename T>
void OcTreeDataNode<T>::allocChildren() {
children = new AbstractOcTreeNode*[8];
for (unsigned int i=0; i<8; i++) {
children[i] = NULL;
}
}
the variable children defined in a namespace gets the address of the allocated array in the member function.
So some other code is responsible to free the allocated memory.
In general it is a bad idea that a member function of a class uses a global variable.
AbstractOcTreeNode** children;
children can be seen as an array of pointer values.
children = new AbstractOcTreeNode*[8];
We initialize it with an array of eight pointer values.
for (unsigned int i=0; i<8; i++) {
children[i] = NULL;
}
Each of the eight children[i] pointer values is initially an uninitialized AbstractOcTreeNode*. We assign the NULL value to each of them. Calling delete beforehand on these uninitialized pointers would be Undefined Behavior.
There is only one memory allocation (new[] is only called once), and its result is kept in children. There is no leak as long as children is eventually cleaned up (using delete[], presumably in the destructor of OcTreeDataNode<T>).
Your confusion is the result of having multiple levels of pointers, at least some of which are owning. I personally also find this code hard to read because of that. In modern C++, you would not perform manual memory management, either for allocating the array of pointers (what about std::vector or std::array) or for the allocation of each AbstractOcTreeNode-dervied instance (which is not shown here). You might find std::vector<std::unique_ptr<AbstractOcTreenode>> children; in modern C++ instead.
So I have a struct as shown below, I would like to create an array of that structure and allocate memory for it (using malloc).
typedef struct {
float *Dxx;
float *Dxy;
float *Dyy;
} Hessian;
My first instinct was to allocate memory for the whole structure, but then, I believe the internal arrays (Dxx, Dxy, Dyy) won't be assigned. If I assign internal arrays one by one, then the structure of arrays would be undefined. Now I think I should assign memory for internal arrays and then for the structure array, but it seems just wrong to me. How should I solve this issue?
I require a logic for using malloc in this situation instead of new / delete because I have to do this in cuda and memory allocation in cuda is done using cudaMalloc, which is somewhat similar to malloc.
In C++ you should not use malloc at all and instead use new and delete if actually necessary. From the information you've provided it is not, because in C++ you also rather use std::vector (or std::array) over C-style-arrays. Also the typedef is not needed.
So I'd suggest rewriting your struct to use vectors and then generate a vector of this struct, i.e.:
struct Hessian {
std::vector<float> Dxx;
std::vector<float> Dxy;
std::vector<float> Dyy;
};
std::vector<Hessian> hessianArray(2); // vector containing two instances of your struct
hessianArray[0].Dxx.push_back(1.0); // example accessing the members
Using vectors you do not have to worry about allocation most of the time, since the class handles that for you. Every Hessian contained in hessianArray is automatically allocated for you, stored on the heap and destroyed when hessianArray goes out of scope.
It seems like problem which could be solved using STL container. Regarding the fact you won't know sizes of arrays you may use std::vector.
It's less error-prone, easier to maintain/work with and standard containers free their resources them self (RAII). #muXXmit2X already shown how to use them.
But if you have/want to use dynamic allocation, you have to first allocate space for array of X structures
Hessian *h = new Hessian[X];
Then allocate space for all arrays in all structures
for (int i = 0; i < X; i++)
{
h[i].Dxx = new float[Y];
// Same for Dxy & Dyy
}
Now you can access and modify them. Also dont forget to free resources
for (int i = 0; i < X; i++)
{
delete[] h[i].Dxx;
// Same for Dxy & Dyy
}
delete[] h;
You should never use malloc in c++.
Why?
new will ensure that your type will have their constructor called. While malloc will not call constructor. The new keyword is also more type safe whereas malloc is not typesafe at all.
As other answers point out, the use of malloc (or even new) should be avoided in c++. Anyway, as you requested:
I require a logic for using malloc in this situation instead of new / delete because I have to do this in cuda...
In this case you have to allocate memory for the Hessian instances first, then iterate throug them and allocate memory for each Dxx, Dxy and Dyy. I would create a function for this like follows:
Hessian* create(size_t length) {
Hessian* obj = (Hessian*)malloc(length * sizeof(Hessian));
for(size_t i = 0; i < length; ++i) {
obj[i].Dxx = (float*)malloc(sizeof(float));
obj[i].Dxy = (float*)malloc(sizeof(float));
obj[i].Dyy = (float*)malloc(sizeof(float));
}
return obj;
}
To deallocate the memory you allocated with create function above, you have to iterate through Hessian instances and deallocate each Dxx, Dxy and Dyy first, then deallocate the block which stores the Hessian instances:
void destroy(Hessian* obj, size_t length) {
for(size_t i = 0; i < length; ++i) {
free(obj[i].Dxx);
free(obj[i].Dxy);
free(obj[i].Dyy);
}
free(obj);
}
Note: using the presented method will pass the responsibility of preventing memory leaks to you.
If you wish to use the std::vector instead of manual allocation and deallocation (which is highly recommended), you can write a custom allocator for it to use cudaMalloc and cudaFree like follows:
template<typename T> struct cuda_allocator {
using value_type = T;
cuda_allocator() = default;
template<typename U> cuda_allocator(const cuda_allocator<U>&) {
}
T* allocate(std::size_t count) {
if(count <= max_size()) {
void* raw_ptr = nullptr;
if(cudaMalloc(&raw_ptr, count * sizeof(T)) == cudaSuccess)
return static_cast<T*>(raw_ptr);
}
throw std::bad_alloc();
}
void deallocate(T* raw_ptr, std::size_t) {
cudaFree(raw_ptr);
}
static std::size_t max_size() {
return std::numeric_limits<std::size_t>::max() / sizeof(T);
}
};
template<typename T, typename U>
inline bool operator==(const cuda_allocator<T>&, const cuda_allocator<U>&) {
return true;
}
template<typename T, typename U>
inline bool operator!=(const cuda_allocator<T>& a, const cuda_allocator<U>& b) {
return !(a == b);
}
The usage of an custom allocator is very simple, you just have to specify it as second template parameter of std::vector:
struct Hessian {
std::vector<float, cuda_allocator<float>> Dxx;
std::vector<float, cuda_allocator<float>> Dxy;
std::vector<float, cuda_allocator<float>> Dyy;
};
/* ... */
std::vector<Hessian, cuda_allocator<Hessian>> hessian;
So I have been trying to implement an arrayStack but I seem to have issues popping more than 100 elements. My program just stops working when it hits hundred. It seems that there is an issue with the push and pop but don't quite understand what my problem is.
#ifndef _ARRAYSTACK_1_HPP_
#define _ARRAYSTACK_1_HPP_
#include <stddef.h>
#include "StackADT.h"
#define DEFAULT_SIZE 50
template<class T>
class ArrayStack_1 : public StackADT<T> {
private:
T *arrayStack;
int index;
int maxSize;
public:
// a constructor for the arrayStack that creates and arrayStack of a given size
ArrayStack_1(int size = DEFAULT_SIZE) {
maxSize = size;
index = 0;
arrayStack = new T[size];
}
public:
// a constructor for the arrayStack that creates and arrayStack of a given size
ArrayStack_1(int size = DEFAULT_SIZE) {
maxSize = size;
index = 0;
arrayStack = new T[size];
}
//a destructor that deletes the arrayStack
~ArrayStack_1() {
delete[] arrayStack;
}
bool Empty() {
return index==0;
}
void Push(T& item = 0) {
if (index<maxSize) {
arrayStack[index]= item;
index+=1;
}else {
T* tempArrayStack = arrayStack; //making a copy of the array stack
maxSize+=1;
arrayStack = new T[maxSize];
for (int i=0; i<maxSize; i++){
arrayStack[i]=tempArrayStack[i];
}
arrayStack[index]=item;
index+=1;
delete[] tempArrayStack;
}
}
T Pop() {
if(arrayStack[index]==0){
return 0;
}else {
T element = arrayStack[index];
index--;
return element;
}
}
}
Likely all you should do is change arrayStack[index]==0 to index == 0 in your Pop function. Otherwise you risk accessing arrayStack with negative index which is undefined behaviour (likely a cause of your crash).
Also, when you are reallocating the stack, you should increase the stack size before the reallocation. I.e. swap these lines:
T* arrayStack = new T[maxSize];
maxSize+=1;
Furthermore, you don't assign the new value of arrayStack to your member variable - you define a new local variable in this code. Overall these lines should read:
this->arrayStack = new T[++maxSize];
(Note, you don't have to write this->arrayStack, simple arrayStack = ... will do the job - it's just there for clarity of intent)
And don't forget to delete tempArrayStack, otherwise you leak memory.
Edit
These lines should also be swapped:
index+=1;
arrayStack[index]=item;
and again, you could use ++ - in this case the postfix version:
arrayStack[index++] = item;
Learn about the difference for example here versus here
You really should step through this code to see what it's doing. I'm not sure how you would successfully make it to 100 iterations.
You need to pay more attention to when you are incrementing/decrementing. Sometimes you increment before you set the item, and other times you increment after you set the item.
You're pushing a reference instead of a pointer (and your arrayStack should be a pointer list).
You should double the size when you hit an overflow condition to ensure you don't have to recreate the array on every push.
You have a substantial memory leak because you never delete arrayStack when you increase its size.
You are allocating a local variable and doing nothing with it.
I am attempting to implement a GradeManager class that internally uses an array of DataVector objects that were created dynamically using the new operator, to record the homework grades for a set of students.
I am struggling to make the constructor/destructor.
Description for the constructor: "This is the only constructor of the class, and it specifies the number of students nStudents and number of homeworks nHWs for the class. You should use these to dynamically set the array sizes."
Any thoughts you have to offer will greatly help! This is what I have so far. Thank you so much!!!
#include <iostream>
#include <cmath>
#include <iomanip>
//DO NOT INCLUDE ANYTHING ELSE!!
using namespace std;
typedef double DataType;//Alias for double type
typedef unsigned int UIntType;//Alias for unsigned int type
class DataVector
{
private:
DataType *m_data; //Pointer to dynamically allocated memory that holds all items
UIntType m_size; //Size of the m_data array
public:
DataVector()
{
m_data = new DataType[10];
for(int i = 0; i < 10; i++){
m_data[i]=0;
}
m_size = 10;
}
DataVector(UIntType initSize, DataType initValue)
{
int arraySize = initSize;
m_data = new DataType[arraySize];
for(int i = 0; i < arraySize; i++){
m_data[i] = initValue;
}
m_size = initSize;
}
~DataVector()
{
delete [] m_data;
m_data = NULL;
}
UIntType GetSize()
{
return m_size;
}
void Reserve(UIntType newSize)
{
int arraySize = newSize;
DataType *new_data;
new_data = new DataType[arraySize];
for(int i = 0; i < m_size; i++){
new_data[i] = m_data[i];}
m_data = new_data;
m_size = newSize;
}
};
class GradeManager
{
private:
DataVector *m_student;//m_student[0], m_student[1], etc correspond to sID 0, 1, etc respectively
UIntType m_nStudents;//Number of students
public:
GradeManager(UIntType nStudents, UIntType nHWs)
{
m_student = new DataVector[nStudents];
m_student->Reserve(nHWs);
m_nStudents = nStudents;
}
~GradeManager()
{
int numOfStudents = m_nStudents;
for(int i = 0; i < numOfStudents; i++)
delete [] m_student;
m_student = NULL;
}
};
Some thoughts:
Like stated in the comment by quantdev, use std::vector<> in the DataVector class - much simpler than using an array, though you cannot limit its size directly (as is done nearly-automatically with an array).
It seems you may have a memory leak and possible segmentation fault in DataVector::Reserve(). You allocate the new memory for new_data, copy the data from m_data into new_data (which brings to mind a thought; what happens if m_size is greater than newSize? IMO, a memory access error, but I'm not sure), then re-point m_data to new_data, without releasing the data stored in m_data in previous calls (say, in the constructor). This will lead to a memory leak.
Also, I'm not entirely sure the method DataVector::Reserve() reserves any space, if that's
what it was meant to do.
Also, the constructor/destructor - in my opinion, at least - for GradeManager look fine, with most of the problems located actually in the DataVector class.
Good luck!
I assume that you are not allowed to use the standard containers such as std::vector<> or std::array<> which could facilitate the job.
Your DataVector constructor and destructor are consistent: you create a new dynamic array and your delete the dynamic array.
However inbetween, there is the function Reserve() that you call in GradeMaster constructor.
Its for loop can go out of bounds, because the new size can be bigger or smaller than the old one. You have to check that i remains in bound of both source and target:
for (int i = 0; i < m_size && i<arraySize; i++){ // check on source and target bounds !!!
Also you create memory leak by not releasing the old objects that you do not need anymore. You have to insert this line after the end of your loop:
delete[] m_data; // insert this to avoid memory leaks
A last point is int the GradeMaster destructor. As you delete the whole array with delete[] you MUST NOT loop and try to delete the array several times ! Deleting the array, will delete all its elements. Just remove the for line.
My class has a generic array of pointers member named A:
T** A
Currently, i delete the array in the destructor in the following way:
~MyQuickInitArray(){
delete [] A;
};
Will this cause a memory leak? if so, should i iterate through the array and call delete on each object?
On a side note - Do I need to call delete [] B if B is an array of integers or does the destructor handles it already?
EDIT:
This is how the allocation occurs:
MyQuickInitArray(int size)
{
if(size <= 0)
{
throw new std::exception;
}
_size = size;
_counter = 0;
A = new T*[size];
B = new int[size];
C = new int[size];
}
MyQuickInitArray(const MyQuickInitArray& myQuickInitArray)
{
_size = myQuickInitArray._size;
_counter = myQuickInitArray._counter;
A = new T*[_size];
for(int i = 0; i<_size ;i++)
{
if(myQuickInitArray.A[i] != NULL)
{
A[i] = new T(*myQuickInitArray.A[i]);
}
}
B = myQuickInitArray.B;
C = myQuickInitArray.C;
}
Will this cause a memory leak?
You can surely count on it if A is an array of pointers. You need loop through the array and delete the pointers yourself.
~MyQuickInitArray {
for (int i =_size; i--;) {
delete A[i];
}
delete [] A;
}
Do I need to call delete [] B if B is an array of integers or does the destructor handle it?
Yes, always delete that which is allocated with new. You can do this inside your class's destructor.
Will this cause a memory leak?
Yes, calling delete[] on the array of pointers without deleting items pointed to by individual elements will cause a memory leak, because "built-in" pointers of C++ do not have ownership semantic. Consider using "smart" pointers, e.g. unique_ptr<T> instead of "plain" ones to avoid calling destructors in a loop.
Do I need to call delete [] B if B is an array of integers
You need to call delete[] on everything that you allocated with new[], regardless of the element type of the array.