How to properly delete a double-pointer array? when I tried this code, memcheck told me that "Use of the uninitialized value of size 8" and "Invalid write of size 4". I couldn't figure out where I did wrong.
struct Node
{
int value;
Node* next;
};
int main()
{
Node** doublePtrNode= new Node* [10];
for (unsigned int i = 0; i < 10; i++)
{
doublePtrNode[i]->value=i;
}
for (unsigned int i = 0; i < 10; i++)
{
delete doublePtrNode[i];
}
delete[] doublePtrNode;
return 0;
}
You are already deallocating what you have allocated but doublePtrNode[i]->value=i; assumes that you've allocated a Node there, but you haven't so the program has undefined behavior.
If you are going to use raw owning pointers, you could fix it like this:
Node** doublePtrNode = new Node*[10];
// now allocate the actual `Node`s too:
for(unsigned i = 0; i < 10; ++i) doublePtrNode[i] = new Node;
// your current assigning loop goes here
// deallocate the `Node`s:
for(unsigned i = 0; i < 10; ++i) delete doublePtrNode[i];
delete[] doublePtrNode;
A much simpler and safer option is to use a std::vector<Node>. That way you do not need any manual memory management. It does it for you.
#include <vector>
int main() {
std::vector<Node> nodes(10);
// your current assigning loop goes here
} // all `Node`s are deleted when `nodes` goes out of scope
you need create every node doublePtrNode[i] before assign on it value
struct Node
{
int value;
Node* next;
};
int main()
{
Node** doublePtrNode = new Node * [10];
for (int i = 0; i < 10; i++)
{
doublePtrNode[i] = new Node{ i,nullptr };
}
for (unsigned int i = 0; i < 10; i++)
{
delete doublePtrNode[i];
}
delete[] doublePtrNode;
return 0;
}
Related
The program is aimed to take a dynamically allocated array and return a new dynamically allocated array with double the size that copies the values in the first one and leaves the rest uninitialized. However, it's getting valgrind errors in main(). Any suggestions on how to fix the memory issues?
#include <iostream>
using std::cout;
using std::endl;
int * doubleSize(int * p, int & cap) {
//create dynamically allocated double size array
int *doubleSize = new int(cap * 2);
//store old array values into new array
for (int i = 0; i < cap; i++) {
doubleSize[i] = p[i];
}
cap = cap * 2;
delete[] p; //deallocate old memory
return doubleSize;
}
int main() {
int cap = 3;
int *p = new int(cap);
//initialize an array
for (int i = 0; i < cap; i++) {
p[i] = i;
}
int *s = doubleSize(p, cap);
for (int i = 0; i < 6; i++) {
cout << s[i] << endl;
}
//deallocate memory
delete p;
delete s;
}
Several problems in the code:
int *p = new int(cap);
and
int *doubleSize = new int(cap * 2);
both allocate a single int with the value cap or cap * 2
Since arrays of int are expected by the rest of the code, these need to be corrected to
int *p = new int[cap];
and
int *doubleSize = new int[cap * 2];
Then
delete p;
delete s;
must be changed to
delete[] p;
delete[] s;
in order to correctly delete arrays.
But!
delete[] p;
already happened back in doubleSize when the array was replaced. It could be removed, but the code would be cleaner with
p = doubleSize(p, cap);
and the variable s being removed instead.
so I have this problem with my hashtable whenever i try to delete all elements from my hashtable and then after that again add new elements to it, there will pop some exception read access violation and its caused when i add new elements to hashtable, and am pretty sure cause am clearing it wrong.My clear method looks like that:
void clear()
{
delete[] arr;
arr = nullptr;
maxSize = 256;
currentSize = 0;
}
my hashtable class:
template<class T>
class hashTable {
private:
unsigned int currentSize;
unsigned int maxSize;
public:
list<T>* arr;
hashTable() {
maxSize = 256;
currentSize = 0;
arr = new list<T>[maxSize];
}
//some interface methods
my main:
hashTable<int>* table = new hashTable<int>();
const int MAX_ORDER = 6;
for (int o = 1; o <= MAX_ORDER; o++)
{
const int n = pow(10, o);
for (int i = 0; i < n; i++)
{
//add element
}
table->clear()
Much appreciate any help. (:
Reproducible Example :http://coliru.stacked-crooked.com/a/12d6d48bd423155b
changed clear() into this :
void clear()
{
delete[] this->arr;
this->maxSize = 256;
this->arr = new list<T>[maxSize]();
this->currentSize = 0;
}
now is way faster and no exceptions thank you all for feedback.
I want to resize the array multiple times.It does that the first time but after that, it throws me an error. When I do it the second time, I get an error _CrtIsValidHeapPointer(PUserData). Can someone help me out?
int main()
{
int size = 8;
int *arr = new int[size];
arr[1] = 25;
arr[2] = 30;
int count = 0; //to check size
for (int i = 0; i < size; i++)
{
count = count + 1;
}
cout << count << endl;
resize(arr, size);
int new_count = 0; //to confirm size change
for (int i = 0; i < size; i++)
{
new_count = new_count + 1;
}
cout << new_count << endl;
resize(arr, size);
int new_count2 = 0; //to confirm size change
for (int i = 0; i < size; i++)
{
new_count2 = new_count2 + 1;
}
cout << new_count2 << endl;
return 0;
}
void resize(int *a,int &size)
{
int newsize = 2 * size;
int *arr_new = new int[newsize];
for (int i = 0; i < size; i++) //copy everything
{
arr_new[i] = a[i];
}
size = newsize; //new value of size
delete [] a;
a = arr_new; //Pointer pointing to new array
delete arr_new;
}
There are two problems with this code:
void resize(int *a,int &size)
{
[...]
delete [] a;
a = arr_new; //Pointer pointing to new array
delete arr_new; // huh????
}
The first problem is that you are calling the delete operator twice; the first call deletes the old array (which makes sense), but then you attempt to delete the newly allocated array also (via delete arr_new). How is the caller going to able to use the newly allocated array when resize() has already deleted it before it returned?
The second problem is that you set a to point to the new array (i.e. a = arr_new;) but a is a local function-argument that goes out of scope when resize() returns, so the calling code will never see its new value. I think you want this instead:
void resize(int * & a,int &size) // note the & before a!
Passing a by reference will allow the caller to see a's new value after resize() returns.
#include<iostream>
using namespace std;
class String {
public:
char *q;
int len;
String() { q = new char[0]; }
String(char * p) {
for (int i = 0;*p!=00; i++) {
len++;
p++;
}
q = new char[len];
for (int i = 0; i < len; i++) {
*q = *p;
p++; q++;
}
for (int i = 0; i < len; i++) {
cout << *q;
q++;
}
}
};
void main() {
String s1;
String s2("My name is navdeep.");
system("PAUSE");
}
Why this is happening i dont knnow, i have tried including cout in the for loop where len is being incremented. there the result is fine. but something goes wrong while copying.
You are not resetting the pointers. p and q should point to the beginning of the arrays before each loop.
Lets consider these lines for a while:
q = new char[len];
for (int i = 0; i < len; i++) {
*q = *p;
p++; q++;
}
for (int i = 0; i < len; i++) {
cout << *q;
q++;
}
First you allocate memory and assign it to q.
Then in the first loop you modify q. and at the end of the loop it will no longer point to the original place, the pointer give to you by the new[] expression. In fact, q will be pointing to memory that is not allocated.
You then continue to print out the memory, but now you are out of bounds and will print indeterminate data, leading to undefined behavior.
You loops needs to work on temporary variable, initially initialized to the same value as q. And you need to reset this temporary pointer between the loops.
I have a 2D pointer matrix in C++ such as,
typedef unsigned char U8;
typedef unsigned int U32;
int M=10;
int m_L=8;
U8** A = new U8*[M];
for (U32 i = 0; i < M; ++i)
{
A[i] = new U8[m_L];
}
After setting value in A0, I will write a function which decide delete or not delete M-2 rows in A, depends on the random number is 0 or 1
void delete_or_not(U8** A,int M)
{
if (rand_num==1){
for (U32 index = M-2; index < M; ++index){
delete[] A[index];
}
}
}
Now, in main function (which contains A memory allocation), I want to free/delete the memory which allocated for A. I can use the code
//free A matrix
for (U32 i = 0; i < M; ++i)
{
if (i < m_L)
{
delete[] A[i];
A[i] = NULL;
}
}
delete[] A;
A = NULL;
My problem is that, I don't know that A is delete (M-2) rows or not. Hence, above code does clearly delete all memory, if my random number is 0. That means, above code only delete correct memory if M-2 rows is deleted in the delete_or_not function. How can delete the A matrix perfectly. Thanks
Finaly, my full code is
typedef unsigned char U8;
typedef unsigned int U32;
int M=10;
int m_L=8;
U8** A = new U8*[M];
for (U32 i = 0; i < M; ++i)
{
A[i] = new U8[m_L];
}
delete_or_not(A,M);
//free A matrix
//Way 1: will miss M-2 row if delete_or_not function did not delete 2 rows.
// It only correct if rand_num=1
for (U32 i = 0; i < M; ++i)
{
if (i < m_L)
{
delete[] A[i];
A[i] = NULL;
}
}
delete[] A;
A = NULL;
//Way 2- It will correct if the size of A is M by M
for (U32 i = 0; i < M; ++i)
{
delete[] A[i];
A[i] = NULL;
}
delete[] A;
A = NULL;
Just set deleted elements to NULL and everything will work fine:
void delete_or_not(U8** A,int M)
{
if (rand_num==1){
for (U32 index = M-2; index < M; ++index){
delete[] A[index];
A[index] = NULL;
}
}
}
Also, this is not very useful:
for (U32 i = 0; i < M; ++i)
{
if (i < m_L)
{
delete[] A[i];
A[i] = NULL;
}
}
There's no point advancing i from 0 to M if you then only "do work" when i is smaller then m_L.
But really, in C++ you should probably use std::vector<std::vector<U8>> instead and simply erase or pop_back to get rid of "rows".
In void delete_or_notyou shall set deleted elements to NULL as already proposed by another answer by Amit.
Then Way 2 of your posted code is correct in both cases.
Calling delete on a NULL is perfectly legal and doesn't hurt at all.
Way 1 is not working and should be removed.
In summary:
void delete_or_not(U8** A,int M)
{
if (rand_num==1){
for (U32 index = M-2; index < M; ++index){
delete[] A[index];
A[index] = NULL; // Add this to your code
}
}
}
// In main somewhere...
// free A
for (U32 i = 0; i < M; ++i)
{
delete[] A[i]; // Not a problem if the element has already been deleted
// because the pointer will be NULL and calling
// delete with NULL is OK (and changes nothing)
A[i] = NULL;
}
delete[] A;
A = NULL;