A memory leak exists in the following function. The trouble I am having is knowing how, when, where, and what to delete. Here is the code:
#include "stdafx.h"
#include <iostream>
void someFunc(double** ppDoubleArray, int length)
{
double* pNewDoubleArray = new double[length];
for(int i = 0; i < length; i++)
{
pNewDoubleArray[i] = 3 * i + 2;
}
*ppDoubleArray = pNewDoubleArray;
}
int main()
{
double dbls[] = { 1, 2, 3, 4, 5 };
double* pArray = dbls;
int length = sizeof dbls / sizeof dbls[0];
std::cout << "Before..." << std::endl;
for(int i = 0; i < length; i++)
{
std::cout << pArray[i] << ", ";
}
std::cout << std::endl;
someFunc(&pArray, length);
std::cout << "After..." << std::endl;
//Expected series is: 2, 5, 8, 11, 14
for(int i = 0; i < length; i++)
{
std::cout << pArray[i] << ", ";
}
std::cout << std::endl;
while(true){ }
return 0;
}
As you can see, I tried what to delete the new array I allocated after I had used it. It actually makes sense that this didn't work, but I am not sure what to do here..
Added delete[] pArray:
#include "stdafx.h"
#include <iostream>
void someFunc(double** ppDoubleArray, int length)
{
double* pNewDoubleArray = new double[length];
for(int i = 0; i < length; i++)
{
pNewDoubleArray[i] = 3 * i + 2;
}
*ppDoubleArray = pNewDoubleArray;
}
int main()
{
double dbls[] = { 1, 2, 3, 4, 5 };
double* pArray = dbls;
int length = sizeof dbls / sizeof dbls[0];
std::cout << "Before..." << std::endl;
for(int i = 0; i < length; i++)
{
std::cout << pArray[i] << ", ";
}
std::cout << std::endl;
someFunc(&pArray, length);
std::cout << "After..." << std::endl;
//Expected series is: 2, 5, 8, 11, 14
for(int i = 0; i < length; i++)
{
std::cout << pArray[i] << ", ";
}
delete[] pArray;
std::cout << std::endl;
while(true){ }
return 0;
}
Does this solve any, if at all memory leaks in this situation?
You are allocating & deleting an array in the function. And you are also returning it.
int main()
{
// This one is allocated on the stack, so it will be deleted when exiting main()
double dbls[] = { 1, 2, 3, 4, 5 };
double* pArray = dbls;
//...
// Your function allocates some memory now pointed at by pArray
someFunc(&pArray, length);
std::cout << "After..." << std::endl;
//Expected series is: 2, 5, 8, 11, 14
for(int i = 0; i < length; i++)
{
std::cout << pArray[i] << ", ";
}
std::cout << std::endl;
while(true){ }
// Your forgot to delete the memory allocated by your function!!! Memory leak!!!
return 0;
}
Here:
*ppDoubleArray = pNewDoubleArray;
delete[] pNewDoubleArray;
You delete the array that you just passed back to the caller. Don't do that delete! It is up to the caller to manage the memory after you pass it back.
Rather than jump through all these hoops, you should consider writing "real" C++ code, using container objects like std::vector which will manage the memory for you.
Did you mean to do this:
void someFunc(double** ppDoubleArray, int length)
{
for(int i = 0; i < length; i++)
{
*ppDoubleArray[i] = 3 * i + 2;
}
}
I don't understand why you'd allocate a new array if your intent is to modify the one passed in.
In someFunc you allocate array, then set pointer passed by the user, to point to it. Upon exiting the function, you delete that array and user ends-up with a pointer to freed memory.
You cannot delete pNewDoubleArray, as you store its address in ppDoubleArray. You have to delete[] pArray, when it is not used anymore or before setting it to another address (when calling someFunc(&pArray, ...) again).
Related
I am new to c++ and learning how to declare, use and delete a two dimensional array of std::string.
Because this is a learning exercise I am ignoring the idea of using vectors (for now).
I wrote a program that creates a small two dimensional array, adds data and then deletes the 2d array trying to use best practices along the way.
Can someone suggest improvements? I am most concerned about cleaning up the 2d array after I'm done using it, so I can avoid the possibility of a memory leak.
Thanks in advance.
#include <iostream>
#include <string>
using namespace std;
void DIM(std::string **marray,unsigned int row,unsigned long cols)
{
if (marray[row] != nullptr) {
delete [] marray[row];
marray[row] = nullptr;
}
marray[row] = new std::string[cols];
}
void DIM_DELETE (std::string **marray,unsigned int row)
{
if (*&marray[row] != nullptr) {
delete[] marray[row];
marray[row] = nullptr;
}
}
void DIM_DELETE_ALL (std::string **marray,unsigned int rows)
{
for (int i=(rows-1); i>-1; i--) {
if (marray[i] != nullptr) {
delete[] marray[i];
marray[i] = nullptr;
}
}//next i
//now take care of marray
if (marray != nullptr) {
delete [] marray;
marray = nullptr;
}
}
std::string **create2darray(unsigned int rows,unsigned int cols)
{
//first create the pointer
std::string **my = nullptr; //create pointer , note: no data portion assigned yet
//now assign a data portion to the pointer (could do above in one step)
my = new std::string*[rows];// elements 0 through rows-1 //assigns data section (an array of std::strings)
//now set newly created rows to nullptr
for (unsigned int i = 0; i<rows; i++) {
my[i] = nullptr;
}
//dim each row for cols columns
for (unsigned int i = 0; i<rows; i++) {
DIM(my,i,cols);//dims the strings (creates data portion) my = new std::string*[x];//
}
return my;//returning a std::string **
}
int main()
{
unsigned int rows = 3;//3 rows (0 through 2)
unsigned int cols = 4;//4 columns (0 through 3)
std::string **myarray = create2darray(rows,cols);//2d array (3 rows, 5 cols)
cout << "2d array created" << endl << endl;
myarray[0][0] = "a0"; //row 0, col 0
myarray[1][0] = "b0"; //row 1, col 0
myarray[2][0] = "c0";
myarray[0][1] = "a1";
myarray[0][2] = "a2";
myarray[0][3] = "a3";
myarray[1][1] = "b1";
myarray[1][2] = "b2";
myarray[1][3] = "b3";
myarray[2][1] = "c1";
myarray[2][2] = "c2";
myarray[2][3] = "c3";
cout << "assigned data to rows 0 to 2 and cols 0 to 3" << endl << endl;
for (unsigned int i=0; i<rows; i++) {
cout << i << ",0: " << myarray[i][0] << " " << i << ",1: " << myarray[i][1] << " " << i << ",2: " << myarray[i][2] << " " << i << ",3: " << myarray[i][3] << endl;
}
cout << endl;
cout << "we are done with 2d array, let's delete it" << endl;
//tested dim_delete (seems to work)
/*
DIM_DELETE(myarray,0);//delete [] myarray[0]; myarray[0] = nullptr;
DIM_DELETE(myarray,1);
DIM_DELETE(myarray,2);
//still need to delete myarray
delete [] myarray;
myarray = nullptr;
*/
//delete all rows and delete the std::string that holds the rows
DIM_DELETE_ALL(myarray,rows);
cout << "array deleted, all done" << endl;
//hold cursor so user can see console messages
do {} while(cin.get()!='\n');
return 0;
}
If the second dimension of your array is constant, I think you can be fine using a single new and delete operators. Something like this:
#include <stdio.h>
#include <string>
int ROWS = 3;
const int COLS = 4;
typedef std::string arr4[COLS];
int main()
{
arr4 *a;
a = new arr4[ROWS];
for (int i = 0; i < ROWS; i++)
for (int j = 0; j < COLS; j++)
a[i][j] = std::to_string(j*ROWS + i);
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
printf("%s ", a[i][j].c_str());
printf("\n");
}
printf("\n");
delete [] a;
}
I have two arrays in a class, both with different sizes. My goal is to copy the second array (nArray) to the the first array (_theArray) using pointers. Below I have included the code of the function in the class, as well as the function in main to test the swap.
I have written the code below, where I try to point the first array to the second array using pointer p (int * p).
void easyArray::resize(unsigned int newSize)
{
// created new dynamic array
int * nArray = new int[newSize];
// init the new array
for (int i = 0; i < newSize; i++) {
nArray[i] = 0;
cout << nArray[i] << " ";
}
if (newSize >= _size) {
for (int i = 0; i < _size; i++) {
nArray[i] = _theArray[i];
}
} else {
cout << "not enough room" << endl;
}
destroy(); //deletes old array
int *p = _theArray; //points old to new array (?)
p = nArray; //sets old array = to new array (?)
}
in main:
void testResize()
{
easyArray a(5);
for(int i = 0; i < a.size(); i++) {
a[i] = i + 100;
}
a.resize(10);
a[9] = 99;
cout << "TEST RESIZE: " << a << endl << endl;
}
Any help is appreciated
Currently when I run this I get the error:
Debug Assertion Failed!
Expression:_CrtIsValiedHeadPointer(block)
Assuming _theArray is a class member variable, you can do _theArray = nArray after the call to destroy() and delete the last 2 lines involving p.
I want to create an array of pointers, and each pointer should keep memory addresses of all elements from another array. But something is goind wrong.
Here is the code:
int main()
{
int a[] = { 1, 2, 3, 4, 5 };
int *b = new int[sizeof(a)];
for (int i = 0; i < sizeof(a); i++)
{
b = &a[i];
}
std::cout << &b[3] << std::endl;
std::cout << &a[3] << std::endl;
return 0;
}
When I expect is similar memory addresses, and values. Bt everything is different.
I think you wanted to do this
int main(int argc, char *argv[])
{
int a[] = { 1, 2, 3, 4, 5 };
unsigned max=sizeof(a) / sizeof(a[0]);
int **b = new int*[max];
for (int i = 0; i < max; i++)
{
b[i] = &a[i];
}
unsigned max=sizeof(a) / sizeof(a[0]);
for (int i = 0; i < max; i++)
{
std::cout << "b[" << i << "]:" << *b[i] << std::endl;
std::cout << "a[" << i << "]:" << a[i] << std::endl;
}
delete[] b;
return 0;
}
Two mistakes. First, when you declare array of pointers you use
int **b;
Secondly, to determine size of array you can use
sizeof(a) / sizeof(a[0])
but be careful here. After passing your array as argument into function it won't work any longer.
sizeof(a) returns the size IN BYTES of a.
To get the number of elements you should divide that for the sizeof(int).
So if you have 5 elements, for example, you'll have sizeof(a) equal to 5*sizeof(int). Divide that for sizeof(int) (which could vary depending on the machine you're working on) and you'll have the exact number of elements.
And I thing you wanna assign b[i] = &a[i], in order to store the addresses in the different elements of b.
Can someone explain me why when i back form function i lost my data from tabOfOffsets. I did the same thing twice and program crash only with the second array.
I printed values of this array on the end of function and everything is clear and correct. Maybe i make mistake somewhere with delete?
Below it is the code.
#include<iostream>
#include <algorithm>
using std::cout;
using std::endl;
void changeSizeOfVector(int *tabValue, int *tabOffsets, int &oldSize, int
newSize) {
int temp = std::min(oldSize, newSize);
int *newTabOfValues = new int [newSize] {0};
int *newTabOfOffsets = new int [newSize] {0};
for (int i = 0; i < temp; i++) {
newTabOfValues[i] = tabValue[i];
newTabOfOffsets[i] = tabOffsets[i];
}
delete[] tabValue;
delete[] tabOffsets;
tabValue = new int [newSize] {0};
tabOffsets = new int [newSize] {0};
for (int i = 0; i < newSize; i++) {
tabValue[i] = newTabOfValues[i];
tabOffsets[i] = newTabOfOffsets[i];
std::cout << tabOffsets[i] << tabValue[i] << endl;
}
oldSize = newSize;
delete[] newTabOfValues;
delete[] newTabOfOffsets;
for (int i = 0; i < newSize; i++) {
std::cout << tabOffsets[i] << tabValue[i] << endl;
}
}
int main() {
int SIZE = 10;
int * tabOfOffsets = new int[SIZE];
int * tabOfValues = new int[SIZE];
for (int i = 0; i < SIZE; i++)
{
tabOfValues[i] = i;
tabOfOffsets[i] = i;
cout << tabOfValues[i] << " : " << tabOfOffsets[i] << endl;
}
changeSizeOfVector(tabOfValues, tabOfOffsets, SIZE, 12);
for (int i = 0; i < SIZE; i++) {
cout << tabOfOffsets[i] << " : " << tabOfValues[i] << endl;
}
delete[] tabOfOffsets;
delete[] tabOfValues;
}
This function declaration is wrong:
void changeSizeOfVector(int *tabValue, int *tabOffsets, int &oldSize, int
newSize);
it means you can change the values of tabOffsets but not the pointer itself in order to make it behave correctly you should declare it as follows:
void changeSizeOfVector(int *tabValue, int **tabOffsets, int &oldSize, int
newSize);
This way you can change the pointer itself and assign a newly allocated array to it.
Code
#include "stdafx.h"
#include <iostream>
void someFunc(double* pDoubleArray, int length)
{
double* pNewDoubleArray = new double[length];
for(int i = 0; i < length; i++)
{
pNewDoubleArray[i] = i * 3 + 2;
}
pDoubleArray = pNewDoubleArray;
}
int main()
{
double dbls[] = { 1, 2, 3, 4, 5 };
int length = sizeof dbls / sizeof dbls[0];
std::cout << "Before..." << std::endl;
for(int i = 0; i < length; i++)
{
std::cout << dbls[i] << ", ";
}
std::cout << std::endl;
someFunc(dbls, length);
std::cout << "After..." << std::endl;
for(int i = 0; i < length; i++)
{
std::cout << dbls[i] << ", ";
}
std::cout << std::endl;
while(true){ }
return 0;
}
Output
Before...
1, 2, 3, 4, 5,
After...
1, 2, 3, 4, 5,
Here's what I am trying to do:
1. Create an array and fill it with some values
2. Pass that array as a pointer to a function that will create a new array and reassign the one that was passed in to the newly created array
3. Print out the changes
I am not seeing any changes though, and I do not know why.
The interface of your function someFunc is wrong. It should require the reference of a pointer's address (or the pointer to a pointer) so that you can return the address of your new array. Otherwise, you are simply modifying a local value.
void someFunc(double*& pDoubleArray, int length)
{
double* pNewDoubleArray = new double[length];
for(int i = 0; i < length; i++)
{
pNewDoubleArray[i] = i * 3 + 2;
}
pDoubleArray = pNewDoubleArray;
}
Your calling main function should then pass a value which can be modified:
int main()
{
double dbls[] = { 1, 2, 3, 4, 5 };
double* pArray = dbls;
// ...
someFunc(pArray, length);
// ...
for(int i = 0; i < length; i++)
{
std::cout << pArray[i] << ", ";
}
// ...
}
Ignoring the memory leak issue that results:
void someFunc(double* & pDoubleArray, int length)
// pass by reference ^^^ the pointer
The line pDoubleArray = pNewDoubleArray; assigns the local copy of the pointer
Either pass the pointer by reference, pass a pointer to it, or return the new value
My preference would be to return the new value, bit that's a style issue.
It is unclear why you are passing the old array to a function which does not use it.
If you are changing individual values, then there is no point in creating a new array instance. If not, then simply create a new array and return it.
So, either change the original array:
void someFunc(double* pDoubleArray, int length)
{
for(int i = 0; i < length; i++)
{
pDoubleArray[i] = i * 3 + 2;
}
}
Or return the new array from the function:
// this indicates that the returned value is
// actually a new instance
double* getNewArray(double* pDoubleArray, int length)
{
double* pNewDoubleArray = new double[length];
for(int i = 0; i < length; i++)
{
pNewDoubleArray[i] = i * 3 + 2;
}
return pNewDoubleArray;
}
An alternative is to pass the input array by reference, but that complicates releasing unused instances.
[Edit]
To clarify this last case:
void someFunc(double** pDoubleArray, int length)
{
double* pNewDoubleArray = new double[length];
for(int i = 0; i < length; i++)
{
pNewDoubleArray[i] = i * 3 + 2;
}
*pDoubleArray = pNewDoubleArray;
}
void main()
{
double dbls[] = { 1, 2, 3, 4, 5 };
double* pArray = dbls;
// this will change what pArray
// points to
someFunc(&pArray, 5);
return 0;
}
As I've commented before, the latter approach will lead to memory leaks if pArray points to a heap allocated array before calling someFunc.