I am trying to add pointers to an object to a vector in a function like this:
vector:
vector<struct Node*> vars;
function:
void fill_vec(){
struct Node* temp;
temp = new Node();
cout << token << endl;
temp->name = token;
temp->value = 0;
cout << temp << endl;
vars.push_back(temp);
}
fill_vec is being called in a while loop that stops when there aren't anymore variable names.
It is adding the correct amount of nodes to the vector, but everything is pointing to the same object. Token is being parsed.
output of above:
a
0x9c6010
b
0x9c6050
printing vector:
void print_vars(){
for(int i = 0; i < vars.size(); i++){
cout << "Name:" << vars[i]->name << endl;
cout << "Value:" << vars[i]->value << endl;
}
}
output:
Name:b
Value:0
Name:b
Value:0
My thought was that when I allocated new memory, the address would change. When I print the address of temp each time I call the function, the address is the same. I was printing the address wrong. The address is different for each call of the function. Thank you in advance for the help.
My thought was that when I allocated new memory, the address would change.
It does indeed.
When I print the address of temp each time I call the function, the address is the same.
That is because you are printing out the address of a local variable, which happens to reside at the same stack memory address each time fill_vec() is called. You should be printing out the memory address of the allocated Node instead.
Change this line:
cout << &temp << endl;
To this:
cout << temp << endl;
As it turns out, it was the token. Token is a char* and I was not using strdup() on it. So every time I updated token, name was being changed in each object.
Related
I ask you questions because there is something I don't understand while studying dynamic allocation in C++.
Can I delete "St" and use "ptr" instead if I move the address stored in St to another pointer "ptr" when the dynamically allocated memory is pointed by the St pointer?
If I delete the "St" dynamic allocation, can I move the address to another pointer and delete the "St" immediately because the allocated space does not disappear but disconnects the pointer "St" from the space?
Below is the code I was writing.
Student is a structure.
int main()
{
case 1:
{
Student* ptr = NULL;
Student* St = new Student[10];
ptr = St;
delete[] St;
St = NULL;
break;
}
case 2:`enter code here`
{
printdata(ptr);break;
}
}
Once you've called delete[] on the pointer you get back from new Student[10], the value of that pointer is indeterminate. Both St and ptr are exactly that, but you reassign St. (Since C++11, use nullptr rather than NULL.)
The behaviour of dereferencing the pointer you get back from new Student[10] following the delete[] is undefined.
You can’t use memory you just freed. Memory at that address might still be usable (event till program closes), but there is no guarantee and program might use it for something else.
Can I delete "St" and use "ptr" instead if I move the address stored
in St to another pointer "ptr" when the dynamically allocated memory
is pointed by the St pointer?
If St points toward your array, you can make ptr point toward it as well, but it is not a transfer. What you actually transfer is the adress of the object you are pointing to. The 2 pointers will point toward the same object.
If you delete the object with delete[] (you delete the object, not the pointer), then the 2 pointers will point toward nothing. So what you actually want to do here is make ptr point toward the same object, and then make St point toward null.
Student* ptr = NULL;
Student* St = new Student[10];
ptr = St;
St = NULL;
Edit : If it may help you understand, here is what you can display ...
int x = 4;
int* p = &x;
cout << "x = " << x << " value of x." << endl;
cout << "&x = " << &x << " adress of x." << endl;
cout << "*p = " << *p << " the value of what p points to." << endl;
cout << "p = " << p << " the actual value of p which is the adress of x." << endl;
Im trying to understand the delete operator in c++.
I could understand the logic behind using pointers and new operator, yet I understood that "The delete operator eliminates a dynamic variable and returns the memory that the dynamic variable occupied to the freestone." p517, Problem solving with C++ 9th edition.
which, I think doesn't align with the third cout statement. and I expected that the third cout statement to be sth similar to the first one.
int main() {
int *p1;
cout << "p1 address: " << &p1 << " and points to the address "<< p1 << " which has the value: " << *p1<< endl;
p1 = new int;
cout << "p1 address: " << &p1 << " and points to the address "<< p1 << " which has the value: " << *p1<< endl;
delete p1;
cout << "p1 address: " << &p1 << " and points to the address "<< p1 << " which has the value: " << *p1<< endl;
cout << endl;
return 0;
}
I would appreciate any explanation :))
delete doesn't have to change the memory your pointer points to. What it actually does is implementation specific.
What delete needs to do is to deconstruct any object at the given address and return the associated memory to the allocation pool. Some debugger might overwrite the value of a variable when freed, but for trivial types no special deconstruction needs to take place - the memory can be returned to the pool as-is. The pointer isn't changed either: after delete p we call p a dangling pointer that holds an address to freed memory. All access through that pointer is undefined behaviour.
Since handling raw pointers and especially dangling pointers is error prone, it's good to know the C++ smartpointers, e.g. unique_ptr:
std::unique_ptr<int> p; // initialised to nullptr
p = std::make_unique<int>(13); // new int with value 13
p = std::make_unique<int>(37); // deleted previous int, assigned new int with value 37
// optional (when p goes out of scope its pointee is deleted automatically)
p.reset(); // deleted the int and reset p to nullptr
When print a pointer without * or & shows an address, I don't know what is this address.
For example:
int *n;
int num = 10;
n = #
cout << n << endl; // Prints 0020F81C
cout << &n << endl; // Prints 0020f828
The result:
I know cout << &n << endl; to print the address of place in the memory.
But what about cout << n << endl; ?
n is referring to "&num", therefore it's the address to the place in memory where num is pointing to.
You've answered your own question. It is an address. The address in memory of whatever the pointer points to, or zero: in this case, the address of 'num'.
Your second 'cout' prints the address of the pointer itself.
I found a function to resize an array and am having trouble understanding how it works (or if it's working properly). For testing I set the "temp" array to a new value and "startCounter" does get assigned to that value, however the memory location for startCounter doesn't change. Here is my code:
int * startCounter;
void resizeArray(int *&arraySent,int origSize,int newSize) {
output << "&arraySent " << &arraySent << endl;
output << "arraySent[0] " << arraySent[0] << endl;
int* temp = new int[newSize];
output << "&temp " << &temp << endl;
for (int i=0; i<origSize; i++) {
temp[i] = arraySent[i];
}
temp[0]=744;
delete [] arraySent;
arraySent = temp;
output << "&arraySent " << &arraySent << endl;
}
//....
startCounter = new int [3];
startCounter[0]=345;
output << &startCounter << endl;
resizeArray(startCounter,3,10);
output << "startCounter[0]" << startCounter[0] << endl;
output << "&startCounter" << &startCounter << endl;
Here is the output I get from this:
&startCounter 0x60fab8
&arraySent 0x60fab8
arraySent[0] 345
&temp 0x82cfe54
&arraySent 0x60fab8
startCounter[0] 744
&startCounter 0x60fab8
My question is, why does the memory location of startCounter not change from 0x60fab8 after deleting it and assigning it to the new "temp" array? Shouldn't it now become 0x82cfe54?
P.S. I understand about vectors and such but am mainly concerned with understanding how this particular function works.
void resizeArray(int *&arraySent,int origSize,int newSize) {
output << "&arraySent " << &arraySent << endl;
outputs the address of the pointer variable, not the address that it holds.
simply omit the address operator to get the (probably) intended effect
&startCounter is the address of the pointer, not the address it points to. it's value won't change. simply use startCounter.
This may a stupid question, but I'm gonna ask it anyway:
Suppose you have a pointer: Object* pointer which points at a dynamically allocated object.
class PointClass
{
Array<Object*> m_array1;
Array<Object*> m_array2;
void Delete1()
{
for (int i = 0; i < m_array1.Length; i++)
{
delete m_array1[i];
}
}
void Delete2()
{
for (int i = 0; i < m_array2.Length; i++)
{
delete m_array2[i];
}
}
}
Now, you put your pointer both in m_array1 and in m_array2.
When you try to delete the arrays, in one of them you will have a pointer which points to a deallocated space, so you can't delete it again!
I can't just assign the pointers NULL after the deletion because it wouldn't affect the pointer in the other array.
How would you solve it?
Well the simplest way would be to use a reference-counting pointer, like those available in boost::smart_ptrs.
Otherwise, you need to assign owners to the pointers - you need to decide which class will be responsible for allocating/deleting that particular pointer. If for some reason you decide that should be this class, then you could remove the duplicates from the arrays by adding all the pointers to a set before enumerating them.
If you have to share pointers in this way, something like a ref counted pointer may work well.
See this site which gives an exposé of various 'smart-pointer' techniques.
Smart Pointers
My initial answer is: Don't do that.
If you absolutely have to for some reason, you could wrap it in a smart pointer
Best solved is not passing the same pointer to both arrays. :P If you really need to, and you also need to reflect that change to all other "same" pointers, a pointer-to-pointer will do.
#include <iostream>
struct Object{};
int main(){
Object* ptr = new Object;
Object** ptrptr = &ptr;
delete *ptrptr;
*ptrptr = 0;
// both print 0
std::cout << *ptrptr << std::endl;
std::cout << ptr << std::endl;
}
On Ideone.
Another way is with a reference-to-pointer.
int main(){
Object* ptr = new Object;
Object*& refptr = ptr;
delete refptr;
refptr = 0;
// both print 0
std::cout << refptr << std::endl;
std::cout << ptr << std::endl;
}
But the second best way is probably a ref-counted smart pointer.
How would you solve it?
By not storing the same pointer in two different places. Doing this creates a duplication of data, and confuses ownership semantics. Who owns the memory pointed to by pointer? Ownership is not clear.
Under normal circumstances, dynamically allocated objects should be owned by the same module that allocated it, and only that module will have direct access to the objects or delete the memory. That's not to say other modules can't get at the data.
As others have suggested use smart pointers to solve your problem. If you have to solve it by writing your own code, I would make each of the delete function also search the "other" array to delete all pointers in the first array that can be found in the other array. And it is a last option option as this would not be my first solution to implement anything as your approach
void Delete2()
{
for (int i = 0; i < m_array2.Length; i++)
{
for (int j = 0; j < m_array1.Length; j++)
{
if (m_array2[i] == m_array1[j])
{
delete m_array1[j]
m_array1[j] = NULL;
}
delete m_array2[i];
m_array2[i] = NULL;
}
}
Then look for ways to optimise it
If I understood your question, you have the same (valid) pointer stored in 2 different arrays.
The problem is that after you delete it on array1, you can't do it again in the second array.
One way to do this is change your array definition to store the memory address of the pointer itself, instead of storing the address of the allocated memory:
const int array_size = 3;
int** m_array1[array_size];
int** m_array2[array_size];
and the rest of the code could be implemented as:
void Delete1()
{
for (int i = 0; i < array_size - 1; i++) // delete all memory but leave the last intact
{
if (*(int*)m_array1[i])
{
cout << "Delete1: erasing #" << i << " with mem addr " << std::hex << *m_array1[i] << std::dec << endl;
delete *m_array1[i];
*m_array1[i] = NULL;
}
}
}
void Delete2()
{
for (int i = 0; i < array_size; i++)
{
if (*m_array2[i])
{
cout << "Delete2: erasing #" << i << " with mem addr " << std::hex << *m_array2[i] << std::dec << endl;
delete *m_array2[i];
*m_array2[i] = NULL;
}
else
{
cout << "Delete2: !!! memory at #" << i << " was already deleted." << endl;
}
}
}
int main()
{
int* num1 = new int(10);
int* num2 = new int(20);
int* num3 = new int(30);
cout << "main: storing " << std::hex << &num1 << " which points to " << num1 << std::dec << endl;
cout << "main: storing " << std::hex << &num2 << " which points to " << num2 << std::dec << endl;
cout << "main: storing " << std::hex << &num3 << " which points to " << num3 << std::dec << endl;
m_array1[0] = &num1;
m_array1[1] = &num2;
m_array1[2] = &num3;
m_array2[0] = &num1;
m_array2[1] = &num2;
m_array2[2] = &num3;
Delete1();
Delete2();
}
Outputs:
main: storing 0xbfc3818c which points to 0x87b6008
main: storing 0xbfc38188 which points to 0x87b6018
main: storing 0xbfc38184 which points to 0x87b6028
Delete1: erasing #0 with mem addr 0x87b6008
Delete1: erasing #1 with mem addr 0x87b6018
Delete2: !!! memory at #0 was already deleted.
Delete2: !!! memory at #1 was already deleted.
Delete2: erasing #2 with mem addr 0x87b6028