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.
Related
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;
}
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.
We were writing a code in our university (learning about Object Oriented Program). We wrote this class and the issue is that, as per my understanding and our teacher the program should crash in the following condition, but in my case it doesn't.
The thing is this line is the culprit
DynamicArray d, f;
f = d;
according to him(rest of the code is attached), since when main ends, deconstructor deletes f and then goes for d, but since pointer was pointing to same mem location in both cases, now it should give error when it tries to delete it, since there is nothing there....but my compiler runs the code perfectly. I am using gcc compiler. Denconstructor at the end of class, rest is to fill dynamic array.
#include <iostream>
#include <ctime>
class DynamicArray{
private:
int *arr;
int size, cap; //cap is the physical size, size is number of elements
public:
DynamicArray(){
arr = nullptr;
size = cap = 0;
}
DynamicArray(int i){
cap = i;
size = 0;
arr = new int[cap];
}
void pushback(int j){
if(cap == 0){
arr = new int[cap];
arr[0] = j;
size++;
cap++;
}
else if(size < cap){
arr[size] = j;
size++;
}
else if(size == cap){
int *arr2 = new int[cap * 2];
int i;
cap *= 2;
for(i = 0; i < size; i++){
arr2[i] = arr[i];
}
arr2[i++] = j;
delete[] arr;
arr = arr2;
}
}
void print(){
for(int i = 0; i < size; i++)
std::cout << arr[i] << " ";
}
~DynamicArray(){
if(arr != nullptr)
delete[] arr;
}
};
int main(){
DynamicArray d, f;
srand(time(nullptr));
int n = rand() % 5;
for(int i = 0; i < n; i++){
d.pushback(rand() % 10);
}
f = d;
f.print();
std::cout << std::endl;
d.print();
return 0;
}
Your code causes so-called "undefined behaviour". Basically, that means anything can happen, including that nothing happens or that whatever happens isn't easily observable. For a more precise definition of "undefined behaviour", you'd have to check e.g. the C++ standard, but there are also many discussions concerning this term here.
Try running your code using e.g. valgrind, it will tell you that your code is broken.
Well consider this:
int * hello = new int[10];
for (register int i = 0; i < 10; i++)
*(hello + i) = i;
int * & hello_ref = hello;
delete[] hello_ref ;
for (register int i = 0; i < 10; i++)
cout << *(hello + i) << std::endl;
Nowhello_ref can succesfully delete the memory which is allocated by new ... From a fact that the reference and pointer are very close how we do the same thing with pointer to pointer to new memory allocated
now consider this
int i = 0;
unsigned int * hello = new unsigned int[6];
for (register int i = 0; i < 6; i++)
*(hello + i) = i;
unsigned int * bye = new unsigned int[4];
for (register int i = 0; i < 4; i++)
*(bye + i) = i;
unsigned int ** del = new unsigned int *[2];
*del = bye;
*(del + 1) = hello;
delete[] * del;
delete[] * (del + 1);
Is there any way that we could delete the new allocated memory for hello and bye with the del pointer to pointer ... these could just clear the data which hello and bye pointed to ....
You just need to delete the array referenced by del:
delete[] del;
You are already deleting the arrays referenced by hello and bye:
delete[] * del;
delete[] * (del + 1);
Though this would be more idiomatic:
delete[] del[0];
delete[] del[1];
Or even better, avoid using new and delete altogether, taking advantage of modern C++ features. What you are writing looks more like C.
#include <array>
#include <numeric>
#include <tuple>
template<typename T, std::size_t N>
std::array<T, N> make_increasing_array(T initial = T())
{
std::array<T, N> array;
std::iota(array.begin(), array.end(), initial);
return array;
}
int main()
{
auto del = std::make_tuple(
make_increasing_array<unsigned int, 6>(),
make_increasing_array<unsigned int, 4>());
auto& hello = std::get<0>(del);
auto& bye = std::get<1>(del);
}
If I understand your question correctly then the answer on the 1st part of your question will be something like this:
...
int * * hello_ref = &hello;
delete[] *hello_ref;
...
About second part, you did exactly what you asked. Those 2 delete do the job. Just add delete[] del; as a final touch.
I am trying to add an array to my Object which contains dynamic array
MyCollection.h
template <typename T>
MyCollection<T>::MyCollection(int size)
{
arraySize = size;
anArray = new T[size];
}
template <typename T>
MyCollection<T>::MyCollection(MyCollection<T>& coll)
{
arraySize = coll.arraySize;
anArray = new T[arraySize];
for (int i = 0; i < arraySize; i++)
{
SetValue(coll.GetValue(i), i);
}
}
template <typename T>
MyCollection<T>::MyCollection(T* myArray, int size)
{
anArray = myArray;
arraySize = size;
}
template<typename T>
void MyCollection<T>::AddAll(T pArray[], int size)
{
int plusSize = size - 1;
int arrayIterator = 0;
arraySize += size;
for (int i = size; i < arraySize - plusSize; i++)
{
anArray[i] = pArray[arrayIterator];
arrayIterator++;
}
}
Main
MyCollection<string> B = MyCollection<string>(new string[3], 3);
B.SetValue("C", 0);
B.SetValue("D", 1);
B.SetValue("E", 2);
string C[3];
C[0] = "X";
C[1] = "Y";
C[2] = "Z";
B.AddAll(C, 3);
B.Display();
In the AddAll method I have error with acces violation. When I add watch anArray[i] = . Is there any idea why that happens? Is it problem with copy construcotr or so ?
In AddAll(), you need to resize the raw array anArray, there is no resizing going on (you just change the numeric value of arraySize, but do not allocate more memory). So you need something like
delete[] anArray;
// ...
anArray = new T[arraySize];
You may also think whether you want to copy the old elements into the newly allocated array, in which case you first have to reallocate with a temporary pointer, then copy into it, then delete the original anArray, and finally assign the temporary pointer to the original anArray, something like:
// save the old size
int oldSize = arraySize;
arraySize += size;
T* tmp = new T[arraySize];
// copy from anArray into tmp, use oldSize
// for(...){...}
delete[] anArray;
anArray = tmp;