Setting a variable equal to a variable that is equal to nullptr - c++

I have an array called my_array of linked lists.
Node* x = my_array[0];
if (head == nullptr)
{
my_array[0] = new Node;
}
How come this one works fine, but
Node* x = my_array[0];
if (head == nullptr)
{
x = new Node;
}
how come this one leaks memory? Aren't they pointing to the same thing? They should be the same, right?

You misunderstood how pointers work. Pointers are variables like any other and their value is a memory address. Nothing more and nothing less.
This line:
Node* x = my_array[0];
Copies the address from my_array[0] to a new variable called x. While the address is the same, the x and my_array[0] are not the same thing. They are two distinct variables holding the same address.
This line:
my_array[0] = new Node;
Re-assigns the address of my_array[0] to a new address of the heap allocated Node object. It overwrites the old address in my_array[0] and thus leaks the memory because the address (and the object in it) was never freed. However you still have it in x so you can still free it and prevent the leak.
This line:
x = new Node;
does essentially the same thing but overwrites the address stored in x instead. This might be fine though because the original address is still in my_array[0] (remember x was just copy of that address) and might be freed later. And also you can still free the new address in x as well too. So the second one might not leak either.
I highly recommend you to watch POINTERS by TheCherno. It is excellent and simple explanation.

x is a variable on its own and it is not an alias for my_array[0]. Changing x only affects the value of x.
Example:
int zero = 0;
int one = 1;
int* arr[] = {&zero};
int* x = arr[0];
x = &one;
std::cout << "*arr[0] = " << *arr[0] << '\n'
<< "*x = " << *x;
Output:
*arr[0] = 0
*x = 1
As you can see, what x points to is changed but the array is not affected. Now, if you want an alias, you should use a reference:
int* arr[] = {&zero};
int*& x = arr[0];
x = &one; // note the &
std::cout << "*arr[0] = " << *arr[0] << '\n'
<< "*x = " << *x;
Output:
*arr[0] = 1
*x = 1
Meaning you should use Node *&x = my_array[0]; or with modern C++, auto& x = my_array[0];.

Related

C++ Pointers and Dynamic Arrays and Delete Operator

Ok so I am going to lay out two programs. Both are dynamic arrays using pointers and the new operator. But one doesn't seem to like the delete operator.
#include <iostream>
int main()
{
int *p;
p = new int[5];
for (int i = 0; i < 5; i++)
{
p[i] = 25 + (i * 10);
std::cout << p[i] << " ";
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
That's the first program. It likes the delete operator just fine. Now the program that dislikes the delete operator:
#include <iostream>
int main()
{
int x;
int *p;
p = new int[5];
*p = 4;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] p;
p = NULL;
return 0;
}
This program compiles just fine. But during execution, it throws an error - free(): invalid pointer: 0xfdb038 .. or whatever the memory address is for that particular execution. So, the question is:
Why can't the delete operator be used in the second case?
I don't want to have memory leak; I don't want the pointer to be dangling.
If I just say p = NULL;, then p = 0, but I believe the pointer is still dangling?, but I'm not sure. Thanks in advance.
Look at this loop in the second piece of code:
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
x = *p;
p++;
*p = x + 1; // <--- Here
}
Notice that in this line, you write to the memory address currently pointed at by p. Since you always increment p and then write to it, you end up writing off past the end of the region that you allocated for p. (If we imagine pOrig as a pointer to where p initially points, then this writes to pOrig[1], pOrig[2], pOrig[3], pOrig[4], and pOrig[5], and that last write is past the end of the region). This results in undefined behavior, meaning that literally anything can happen. This is Bad News.
Additionally, delete[] assumes that you are passing in a pointer to the very first element of the array that you allocated. Since you've incremented p so many times in that loop, you're trying to delete[] a pointer that wasn't at the base of the allocated array, hence the issue.
To fix this, don't write to p after incrementing it, and store a pointer to the original array allocated with new[] so that you can free that rather than the modified pointer p.
You have to delete the pointer that you got from new. However, in your second code you did p++ which changed the pointer. Therefore you tried to delete a pointer you didn't get from new and delete crashes.
To fix this type of error never use new. Instead use std::vector<int> p;. Since you never need new you cannot forget a delete.
Problem is changing p in p++.
You should always store (to delete) original pointer. Like this:
#include <iostream>
int main()
{
int *original = new int[5];
int *p = original;
for (int i = 0; i < 5; i++)
{
std::cout << *p << " ";
int x = *p;
p++;
*p = x + 1;
}
std::cout << std::endl;
delete [] original;
return 0;
}

Basic C++ String Pointers

Why it is not throwing a error in line 2?
char *p = "Hello";
p = "Bye";
*p is the variable so p is the address of the variable *p.
Please someone explain me what is the case in above code?
*p is not "the variable". p is the variable and it is a pointer. C and C++ have the odd looking declaration syntax in which you declare a variable with the same kind of syntax used to access the variable.
char *p;
In that declaration we are declaring p, not *p but declaring p to be the thing p would need to be for *p to be a char
char *p = "Hello";
Now it may be even another step less intuitive, because the thing on the right of the = is the initial value for p not the initial value for *p. That is how C and C++ work and is easy to get used to and understand, even if the meanings of the left and right side of that initially seem counter-intuitive.
So your example:
char *p = "Hello";
p = "Bye";
I can see why someone who doesn't know C or C++ might think there is a different level of indirection to the use of p on the first line vs. the second. But actually on both lines p is a pointer and the address of a text literal is being stored in that pointer.
Those are not C++ String Pointers, those are C-Strings. It is not throwing a error because a string-literal is itself a pointer to the first element. p is the pointer, *p is the first element of you String
Here is a example
int firstvalue = 5, secondvalue = 15;
int * p1, * p2;
p1 = &firstvalue; // p1 = address of firstvalue
p2 = &secondvalue; // p2 = address of secondvalue
*p1 = 10; // value pointed to by p1 = 10
*p2 = *p1; // value pointed to by p2 = value pointed to by p1
p1 = p2; // p1 = p2 (value of pointer is copied)
*p1 = 20; // value pointed to by p1 = 20
cout << "firstvalue is " << firstvalue << '\n';
cout << "secondvalue is " << secondvalue << '\n';
return 0;
}
The problem you have is p is the variable with its pointer.
In the first case, p is assigned the address of the string. In the second case, p is reassigned the address of another string
EDIT - String literals are not allocated in the stack. Thanks to Q

c++ array iteration with addresses - heap corruption

I am new to c++ and trying out some stuff.
So recently I tried to create an int array on the heap and iterate it with addressation instead the standard way with [x].
Everytime I execute my code I get a heap corruption error.
I tried several things (also searched here on stackoverflow) but could not find any answers.
int* p = new int[5];
for (int i = 0; i <= 4; i++){
/*p[i] = i;
cout << p[i] << endl;*/ //This is the standard way and works
*p = i;
cout << *p << endl;
p = (p + sizeof(*p)); //iterate the pointer through the heap addresses
}
delete[] p;
The application runs and shows me the filled array values {0,1,2,3,4} but then crashes.
I get following error message:
HEAP CORRUPTION DETECTED: after CRT Block (#225) at 0x00C31B68.
CRT detected that application wrote to memory after end of heap buffer...
Thanks in advance
When you do this
p = (p + sizeof(*p));
you are taking sizeof(int) int-sized steps across the array, going beyond its bounds.
You need to take single steps:
p = (p + 1);
or
++p;
But note that after doing that, p no longer points to any place you can call delete[] on. You need to keep a pointer to the original address:
int* arr = new int[5];
int* p = arr;
....
delete[] arr;
But you have no reason to allocate the array with new in the first place.
int arr[5];
int * p = arr;
....
p = (p + sizeof(*p));
results in a jump of 4 with every iteration, as sizeof(int) is equal to 4. Hence, you are going out of bounds.
The standard way, that is :
p[i] = i;
cout << p[i] << endl;
is correct, as i increases by 1 in every iteration.
This statement
p = (p + sizeof(*p));
is wrong.
First of all you are changing the initial value of pointer p that points to the allocated memory.So this statement
delete[] p;
will be wrong for this pointer because initial value of p was changed.
Secondly expression p + sizeof(*p) means that you want to move the pointer right to sizeof( *p ) elements. If for example sizeof( *p ) is equal to 4 then after statement
p = (p + sizeof(*p));
p will point to fifth element of the array (that is with index 4).
Valid code can look the following way
int* p = new int[5];
for ( int i = 0; i < 5; i++){
*( p + i ) = i;
cout << *( p + i ) << endl;
}
delete[] p;
In pointer arithmetics an expression p + i, where p is a pointer to an array's element and i is integer, is equivalent to &(p[i]), that is a pointer to the array's element i positions after the one pointed at by p.
That's why stepping to the next element is performed by p = p+1 (or equvalently p += 1 or simply ++p).
Note however the incrementation does no checking for the array bounds – you're able to safely access the next item(s) provided they belong to the same array. If you step beyond the last item of an array you may get memory access error or just read some garbage.
See for example
http://www.tutorialspoint.com/cplusplus/cpp_pointer_arithmatic.htm
https://www.eskimo.com/~scs/cclass/notes/sx10b.html

Beginner C++ programmer, confused over dynamic arrays

I am trying to create a class analogous to the built-in vector class in C++. I have tried to follow all the instructions in Walter Savitche's textbook, but just can't get it to work properly.
The code was written using the Code::Blocks IDE and compiled using the gcc compiler.
The thing I think I'm missing is the relationship between array parameters and a pointer that points to an array.
This is what I understand about normal variables:
int *p1, *p2, *p3, *p4, a;
a = 5; // variable of type int with value 5
p1 = &a; // p1 now points to the value 5
p2 = p1; // p2 now also points to the value of a
p3 = new int; // p3 points to an anonamous variable of type int with undefined value
*p3 = *p1 // value of variable changed to the value of a, namely 5, but doesn't point to a
p4 = new int; // p4 points to an anonamous variable of type int with undefined value
*p4 = 5; // value of variable changed to 5
p4 = p1 // p4 now also points to the value of a
This is what I essentially don't understand about arrays and pointers that point to arrays
int *p1, *p2, *p3, *p4, a[3] = {4, 5, 6}; // a points to the first indexed element of the array, namely 4
p1 = a; // p1 points to the exactly the same thing as a
p2 = new int[3]; // p2 points to an array of base type int with undefined values
p2[0] = 8; // is this the correct usage? is p2 "dereferenced"
p2[1] = 9;
p2[2] = 10;
p2[2] = p1[2]; // again is this correct? is the third element of the array pointed to by p2 now equal to 6?
*p3 = a // what does this mean?
p4 = new int[4]; // p4 points to an array of base type int with undefined values
p4[0] = p2[0];
p4[1] = p2[1];
p4[2] = p2[2];
p4[3] = 3
p2 = p4 // p2 now points to p4, but what happens to the array p2 was pointing to?
delete [] p2; // does this destroy the pointer and the array it is pointing to or just one or the other?
For completeness sake my class is defined as follows:
class VectorDouble
{
public:
// constructors
VectorDouble(); // default constructor
VectorDouble(int init_count); // user specified
VectorDouble(const VectorDouble& vd_object); // copy constructor
// destructor
~VectorDouble();
// accessors
int capacity_vd(); // get max_count
int size_vd(); // get amt_count
double value_at(int index); // get value of "value" at index i
// mutators
void push_back_vd(double put_at_end); // insert new element at end of "value"
void reserve_vd(int incr_capacity); // set max_count
void resize_vd(int incr_size); // set amt_count
void change_value_at(double d, int index); // set value of "value" at index i
// overloaded =
void operator =(const VectorDouble& vd_object_rhs);
// other
friend bool operator ==(VectorDouble vd_object1, VectorDouble vd_object2);
private:
double *value; // pointer that points to array of type double
int max_count; // the memory allocated to the array
int amt_count; // the amount of memory in use
};
And the troublesome function is:
void VectorDouble::push_back_vd(double put_at_end)
{
double *temp;
if(amt_count == max_count)
max_count += 1;
temp = new double[max_count];
for(int i = 0; i < amt_count; i++)
temp[i] = value[i];
amt_count += 1;
temp[amt_count] = put_at_end;
value = temp;
}
The member function just seems to insert 0.0 instead of the user input, I have no idea why...
In main:
VectorDouble vec1(10);
double dd;
cout << "Enter 3 doubles to vec1:\n";
for(int i = 0; i < 3; i++)
{
cout << i << ": ";
cin >> dd;
vec1.push_back_vd(dd);
}
cout << "The variables you entered were:\n";
for(int i = 0; i < 3; i++)
cout << i << ": " << vec1.value_at(i) << endl;
I enter:
12.5
16.8
15.2
I get back:
0
0
0
I fixed it! Only problem is that the mistake was exceedinly simple. Sorry to waste everybodies time, but thanks to all, I did learn quite a lot!
The mistake was my placement of amt_count += 1;, I'm used to arrays indexed from 1 not zero (I have done a lot of coding in the R language). The corrected code with the memoery leak taken care of is:
void VectorDouble::push_back_vd(double put_at_end)
{
double *temp;
if(amt_count == max_count)
max_count += 1;
temp = new double[max_count];
for(int i = 0; i < amt_count; i++)
temp[i] = value[i];
temp[amt_count] = put_at_end;
amt_count += 1;
delete [] value;
value = temp;
}
This is what I understand about normal variables
All correct, with the caveat that I'd avoid the terminology "points to the value x"; you're pointing to the object, which in turn has value x.
This is what I essentially don't understand about arrays and pointers that point to arrays
You're confusing pointers with arrays. In int a[3], a is an array. It is not a pointer. It is an array.
*p3 = a isn't valid, so it means nothing.
p2 now points to p4, but what happens to the array p2 was pointing to?
You've leaked it.
// does this destroy the pointer and the array it is pointing to or just one or the other?
It destroys the thing you new'd, that the pointer is pointing to. i.e. the array
Otherwise all correct.
As for your vector implementation, the main problem is that temp[amt_count] is an overflow because you've already incremented amt_count. Also, vector implementations typically grow exponentially rather than on-demand. Finally, you're leaking the previous storage.
Using different terminology might help you:
A pointer is just an ordinary variable. Instead of holding an integer, a float, a double, etc., it holds a memory address. Consider the following:
int* p = nullptr; // p has the value "nullptr" or null memory address
int i = 5; // i has value 5
p = &i; // p now has the value of the address of i
The ampersand gets the address of a variable.
An asterisk dereferences a pointer; that is it will get the value stored in the memory address the pointer holds:
cout << *p << endl; // Prints whatever is stored in the memory address of i; 5
As for your vector implementation, try moving this line amt_count += 1; to below this line:
temp[amt_count] = put_at_end;, as you're trying to access beyond the end of your array.
Most of your understanding is correct. But...
a[3] = {4, 5, 6}; // a points to the first indexed element of the array, namely 4
Although arrays and pointers can be indexed and treated in a similar fashion, they are different, and their differences can lead to some sneaky bugs; so be careful with this statement.
*p3 = a // what does this mean?
This is invalid. Your types don't match: *p3 is an integer, a is an array.
p2 = p4 // p2 now points to p4, but what happens to the array p2 was pointing to?
The array p2 was pointing to is now leaked memory. This is bad.
delete [] p2; // does this destroy the pointer and the array it is pointing to or just one or the other?
The value of the pointer does not change. However, the memory it points to is deallocated, so dereferencing it will give you undefined results. It's best to set p2 = nullptr; after deleting it.
This answer might help with your understanding of arrays and accessing their elements.
"p2 now points to p4, but what happens to the array p2 was pointing to?"
It is 'leaked', this means its still allocated but there is no way to reach it anymore. If you keep doing this is the same program your memory size will keep growing
Other languages (Java, c#,...) have 'garbage collectors' that detect when this happens and will free the memory automatically
C++ solution to this problem is to never user naked arrays and pointers. Instead you use std::vector and std::shared_ptr; these will clean up for you
Your function is really wrong...
void VectorDouble::push_back_vd(double put_at_end)
{
double *temp;
if(amt_count == max_count)
max_count += 1;
temp = new double[max_count];
for(int i = 0; i < amt_count; i++)
temp[i] = value[i];
amt_count += 1;
temp[amt_count] = put_at_end;
value = temp;
}
Notice that in each call you allocate new array (even if there's still space), copy everything in it and leak memory (old array)...
Here is a slightly corrected version, but it's not guaranteed to be completely OK (;
void VectorDouble::push_back_vd(double put_at_end)
{
if(amt_count == max_count)
{
max_count += 1;
double *temp = new double[max_count];
for(int i = 0; i < amt_count; i++)
temp[i] = value[i];
delete[] value;
value = temp;
}
value[amt_count] = put_at_end;
amt_count += 1;
}

How to convert int* to int

Given a pointer to int, how can I obtain the actual int?
I don't know if this is possible or not, but can someone please advise me?
Use the * on pointers to get the variable pointed (dereferencing).
int val = 42;
int* pVal = &val;
int k = *pVal; // k == 42
If your pointer points to an array, then dereferencing will give you the first element of the array.
If you want the "value" of the pointer, that is the actual memory address the pointer contains, then cast it (but it's generally not a good idea) :
int pValValue = reinterpret_cast<int>( pVal );
If you need to get the value pointed-to by the pointer, then that's not conversion. You simply dereference the pointer and pull out the data:
int* p = get_int_ptr();
int val = *p;
But if you really need to convert the pointer to an int, then you need to cast. If you think this is what you want, think again. It's probably not. If you wrote code that requires this construct, then you need to think about a redesign, because this is patently unsafe. Nevertheless:
int* p = get_int_ptr();
int val = reinterpret_cast<int>(p);
I'm not 100% sure if I understand what you want:
int a=5; // a holds 5
int* ptr_a = &a; // pointing to variable a (that is holding 5)
int b = *ptr_a; // means: declare an int b and set b's
// value to the value that is held by the cell ptr_a points to
int ptr_v = (int)ptr_a; // means: take the contents of ptr_a (i.e. an adress) and
// interpret it as an integer
Hope this helps.
use the dereference operator * e.g
void do_something(int *j) {
int k = *j; //assign the value j is pointing to , to k
...
}
You should differentiate strictly what you want: cast or dereference?
int x = 5;
int* p = &x; // pointer points to a location.
int a = *p; // dereference, a == 5
int b = (int)p; //cast, b == ...some big number, which is the memory location where x is stored.
You can still assign int directly to a pointer, just don't dereference it unless you really know what you're doing.
int* p = (int*) 5;
int a = *p; // crash/segfault, you are not authorized to read that mem location.
int b = (int)p; // now b==5
You can do without the explicit casts (int), (int*), but you will most likely get compiler warnings.
Use * to dereference the pointer:
int* pointer = ...//initialize the pointer with a valid address
int value = *pointer; //either read the value at that address
*pointer = value;//or write the new value
int Array[10];
int *ptr6 = &Array[6];
int *ptr0 = &Array[0];
uintptr_t int_adress_6 = reinterpret_cast<uintptr_t> (ptr6);
uintptr_t int_adress_0 = reinterpret_cast<uintptr_t> (ptr0);
cout << "difference of casted addrs = " << int_adress_6 - int_adress_0 << endl; //24 bits
cout << "difference in integer = " << ptr6 - ptr0 << endl; //6