C++ Deleting pointer with function - c++

I have one question. Is it possible to delete a pointer with function? This is my example:
void deletePointer(auto* pointer)
{
delete pointer;
pointer = nullptr;
}
int main()
{
int value = 5;
int* value_ptr = &value;
//Some code
deletePointer(value_ptr);
return 0;
}
And it doesn't work. I also tried adding "inline" keyword to function and with lambda.
auto deletePointer = [&](auto* pointer) -> void
{
delete pointer;
pointer = nullptr;
}
I think it only deletes pointer inside of function, lambda. Is it possible to make function that will delete pointer, which is passing to function?

Solution.
I got to know that delete can be used only when object is creating using new. So I changed code a bit.
#include <iostream>
void deletePointer(auto*& pointer)
{
delete pointer;
pointer = nullptr;
}
int main()
{
int* ptr = new int(5);
deletePointer(ptr);
if (ptr == nullptr) std::cout << "Succeed";
else std::cout << "Failed";
return 0;
}
And given output from code is: Succeed.
So now everything works.
Thanks for help :)

Related

How to check invalid address/deleted pointer?

I'm pretty new to c++ and I'm stuck at this problem.
I append a struct pointer(Bar*) to a vector and that struct have a pointer class member(Foo*).
struct Bar
{
const int var{ 0 };
Foo* m_foo{ nullptr };
};
std::vector<Bar*> list;
int main()
{
Bar* p_Bar = new Bar;
p_Bar->m_foo = new Foo;
list.emplace_back(p_Bar);
}
I have a thread that checks validity of these pointers. Once I delete those pointers, vector element should exist and I should check whether both pointers are valid or not.
When any of them is invalid, I should erase that vector element(after check I mean).
Here's my try:
#include <iostream>
#include <vector>
#include <thread>
class Foo
{
public:
Foo() {};
const int var{ 5 };
};
struct Bar
{
const int var{ 0 };
Foo* m_foo{ nullptr };
};
std::vector<Bar*> list;
bool _check = true;
void Check()
{
while (_check)
{
for (int c = 0; c < (int)list.size(); c++)
{
Bar* p = list[c];
if (p)
{
if (p->m_foo)
{
std::cout << "m_foo->var:" << p->m_foo->var << "\nEnter anything to delete the element: ";
}
else
{
std::cout << "m_foo was nullptr";
}
}
else
{
std::cout << "Element was invalid";
}
}
std::this_thread::sleep_for(std::chrono::duration(std::chrono::seconds(2)));
}
}
int main()
{
Bar* p_Bar = new Bar;
p_Bar->m_foo = new Foo;
list.emplace_back(p_Bar);
std::thread thread1(Check);
thread1.detach();
std::string t;
std::cin >> t;
if (list[0]->m_foo)
delete list[0]->m_foo;
if (list[0])
delete list[0];
list.clear();
std::cin >> t;
_check = false;
return 0;
}
To check whether the pointer was deleted or not, I should use NULL or nullptr which actually means 0.
But once the pointer is deleted, the address will be something like this 0xFFFFFFFFFFFFFFFF and IDE will throw this kind of exception:
Exception thrown: read access violation.
p->m_foo was 0xFFFFFFFFFFFFFFFF.
How to check whether the pointer's deleted/pointer's address is valid or not?
How to check whether the pointer's deleted/pointer's address is valid or not?
It isn't possible to check whether a pointer is valid or invalid. If a pointer is valid or null, then you can check which one it is. If a pointer is invalid, then the result of the comparison will be unspecified.
Besides comparing an invalid pointer, your program has another bug: You're deleting in one thread, and accessing the pointer in another without synchronising the operations. Similarly, you're accessing the elements of the vector while its elements are removed in another thread. The behaviour of the program is undefined.
P.S. Avoid owning bare pointers.
You could use automatic_ptr class instead classic in-build pointer.
You can develope yourself, or use eg. std::unique_ptr and std::shared_ptr.
Principe of this classes is, that pointer is encalupsed in thos class and class count external links (pointers...) and store it to internal attribute.
In each book of C++ is example for it.

Why access deleted pointer won't crash the program?

#include <iostream>
#include<list>
using namespace std;
template <class T>
class Ptr {
public:
Ptr() {
a = nullptr;
l.push_back(0);
}
std::list<int> l;
void print_this() {
cout<<this<<endl;
}
protected:
int *a;
};
int main()
{
Ptr<int> *ptr = new Ptr<int>();
delete ptr;
//ptr = nullptr; //if uncomment this line will crash
auto p = &(ptr->l);
cout<<"p is "<<p<<endl;
ptr->print_this();
ptr->l.push_back(1);
cout<<"size is "<<ptr->l.size()<<endl;
cout<<"end";
return 0;
}
I run code here: https://www.programiz.com/cpp-programming/online-compiler/
output is :
p is 0x5628eb47deb0
0x5628eb47deb0
size is 2
end
if I set ptr to nullptr after delete, it will crash at push_back. But still fine when I access the list.
How is it even possible that I push data to a dangling pointer without crashing it??
When you have a pointer to a class, and call a non-virtual function on it, whatever the address is at the pointer will be considered the this pointer. Even if it is zero. As long as you don't try to access members at that address, you should have no problem printing the this poniter.
struct A {
void printThis() {
printf("%d\n", this);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A * a = (A*) 777;
a->printThis(); // will print 777
a = NULL;
a->printThis(); // will print 0
return 0;
}
When you delete a pointer and don't set its address to null, the previous address value is kept.
Accessing a deleted pointer is undefined behavior. It is not required to crash. It just may be that the random data that you are pointing to has some meaning somewhere else in the program. It may even be your old data. Deleting a pointer tells the system it can reuse that memory, but it may not have had time to reuse it yet, and so the old data could still be visible.
Finally your program crashes when you uncomment your line because that sets ptr = 0, and &(0x0000000->l) is an invalid memory reference.
Pointer continues to reference to the address after you delete it. You can still use the pointer but there will be trash(mostly) in the address.
#include <iostream>
using namespace std;
int main()
{
int a = 1;
int *ptr_a = &a;
int *ptr = &a;
cout << *ptr_a << endl;
cout << *ptr << endl;
delete ptr;
*ptr_a = 2;
cout << *ptr << endl;
}
Result:
1
1
2

Pointer to class field as lambda argument

Why if we pass a class field pointer int* value in a lambda, then doesn't change value?
struct A {
A() {
auto f = [](int* value) {
value = new int(0);
};
f(value);
}
int* value = new int(42);
};
int main()
{
A obj{};
std::cout << *(obj.value) << std::endl;
}
Changes made to a function parameter are not visible to the caller, unless you take it by reference.
In your case, you would simply need to do
auto f = [](int* &value) {
value = new int(0);
};
Now changes to the parameter value are reflected in the member value.
Note that in your example, (without the reference), the compiler would warn that you are setting value but not using it.
Also, this might solve the specific question, but you are still leaking memory here.
your code isn't compilable - you cannot assign int* to int here: value = int(0);.
I have tried your code with fixed mentioned error:
struct A {
A() {
auto f = [](int* value) {
*value = int(0); // here value is being changed as expected
};
f(value);
}
int* value = new int(42);
};
int main()
{
A obj{};
std::cout << *(obj.value) << std::endl;
}
Everything works fine - passed value pointer to the f lambda is being changed from 42 to 0 value after constructor of struct is called.

How do I return a pointer from a class member function e.g. size_t * class :: function(); and use a class destructor ~size_t*class::function();

I am at the point learning classes/destructors in c++ and the need to return a pointer from a class member:
size_t * classname :: function();
but it doesn't work.
My logic is to declare a class variable e.g. classname * p_p = classfunction(data); that should access the class member:
size_t * classname :: classfunction(data)
{
//... do something ...
new p_p;
return p_p;
}
So the pointer address in theory gets returned to the main() variable p_p each time the member function of the class gets called.
Or should but doesn't and the program crashes somehow but not even sure on which point.
There is no compiler warning or error and the
debugger doesn't stops anywhere and I find nothing on returning a pointer from a class member function at all nor that it isn't allowed or something.
Also if there IS a syntax to return a pointer from a class member function I would need to have a syntax for delete the "new p_p".
So my question is: Should it work and how would I get this running or why is that maybe it is not working or forbidden? In my logic it should be a proper way but I may be wrong somehow and classes doesn't support this function completely.
EDIT:
Thanks to your answers and comments I got the pointer returned from the class member. (Also changed size_t to int since its just a pointer.) Like you suggested in the comments I added a minimal reproducible example:
#include <iostream>
using namespace std;
//########## class without ~ destructor ##########
class classname
{
public:
int *ptr;
int *classfunction(int);
void delete_classfunction(int*);
};
void classname::delete_classfunction(int*ptr)
{
delete[] ptr;
ptr = nullptr;
}
int *classname :: classfunction(int value)
{
int* ptr = new int[value]; //no delete?
ptr[0] = 5;
return ptr;
}
//########## class with ~destructor ##########
class classname_c
{
public:
int *ptr;
int value;
*classname_c(int );
void print(int*);
~classname_c();
};
void classname_c::print(int* ptr)
{
cout << ptr[0] << " shows value" << endl;
}
*classname_c::classname_c(int value)
{
int* ptr = new int[value];
ptr[0] = value;
} /*Brings warning: control reaches end of non-void function [-Wreturn-type]
48 | }
| ^*/
classname_c::~classname_c ()
{
cout << ptr[0] << endl;
delete[] ptr;
ptr = nullptr;
cout << ptr[0] << endl;
}
int main()
{ //class and deleting it myself calling the function delte
int value = 3;
int *ptr;
classname call;
ptr = call.classfunction(value); //create new ptr
cout << ptr[0] << " shows value" << endl;
call.delete_classfunction(ptr); //free memory
cout << ptr[0] << " shows value succ. deleted" << endl;
//class with destructor
classname_c dest(value);
dest.print(ptr);
cout << ptr[0] << " shows value succ. deleted" << endl; //its not!
return 0;
}
brings the following output:
5 shows value
0 shows value succ. deleted //How it should be
3 shows value
3 shows value succ. deleted //but its not, why? What did I do wrong?
Press <RETURN> to close this window...
Now I am not sure if/when the ~destructor is working or how I can test if I created the destructor right, because the ptr value is not deleted.
Also can I fix the
warning: control reaches end of non-void function [-Wreturn-type]
48 | }
| ^
It is perfectly fine to return a pointer from a member function, although returning a pointer to an allocated size_t seem a bit overkill.
What you want is probably something like this:
#include <iostream>
class cls
{
public:
size_t *ptr_func();
};
size_t *cls::ptr_func()
{
size_t *p = new size_t(42);
return p;
}
int main()
{
cls c;
size_t *p = c.ptr_func();
std::cout << (void *)p << '\n';
std::cout << *p;
delete p;
}
This may not answer your question but it might illustrate why this is not working how you expect. When you call a member function of a class, i.e. classname::function(), you need to have an instance of that class on which to call it. Something which has been defined like
class classname {
public:
classname() {ptr = new int(0);}
size_t* function();
~classname();
int* ptr;
};
size_t* classname::classfunction() {
size_t* ptr = new size_t();
return ptr;
}
Cannot be called by
classname * p_p = classfunction();
because classfunction() is not being called on an instance of classname and because classname is not size_t so you can't assign classname to the return from a function which returns type size_t unless a cast from one to the other has been explicitly defined (same goes for classname* and size_t*). You can do something like this
classname cls;
size_t* ptr = cls.classfunction();
Also note that destructors are not used for member functions, only for classes, so the syntax ~size_t*class::function() doesn't really make sense.
If you are trying to get a pointer to a class instance you can simply do
classname * ptr = new classname();
and put your //... do something ... in a constructor.
Edit
The use of a destructor is to perform the
[...] necessary cleanup needed by a class when its lifetime ends.
This means that the destructor is called when the instance of said class goes out of scope or is manually deleted. So when you have a class defined as above, with the destructor
classname::~classname() {
delete ptr;
}
This means that ptr will be deleted when the instance of classname reaches the end of its "lifetime". E.g.
int main() {
classname* cls = new classname();
// cls->ptr == int(0)
delete cls; // Calls ~classname()
// cls->ptr == NULL
}
The same is true for stack allocation (classname cls();) and in either case the destructor would be called automatically at the end of main (if that instance had not already been manually deleted).
Now what you can't do is delete a pointer that was allocated outside the class instance - if you want to be able to control a pointer like that while still having it accessible from outside the class you can make it a public member, as I did in the edited class declaration. This allows you to access the pointer from outside the class and then still delete it with the destructor,
int main() {
classname* cls = new classname();
// cls->ptr == 0
cls->ptr = 3;
// cls->ptr == 3
delete cls;
// cls->ptr == NULL
}
Hopefully that offers some clarity.
The warning is because of the constructor
*classname_c::classname_c(int value) {//...}
.... don't do this until you really know what you're doing, if you want a pointer to an instance of the class the constructor should be
classname_c::classname_c(int value) {//...}
and you should create the instance with
classname_c* cls = new classname_c(value);

How to pass a pointer variable as a reference parameter?

When you have a function like this, the formal parameter is a reference, it becomes another name for the actual argument, so that when we modify the formal parameter inside the function, the original variable outside the function is changed.
void add_five(int& a)
{
a += 5;
}
int main()
{
int number = 3;
add_five(number);
std::cout << number << std::endl; // prints 8
return 0;
}
I have some code which works on a linked lists. And I am passing two Node*s into the function.
void LinkedList::move_five_nodes(Node* ptr1, Node* ptr2) { ... }
...
void LinkedList::anotherFunction()
{
Node* leader;
Node* trailer;
...
move_five_nodes(leader, trailer);
...
}
I think that the rvalues memory addreses inside the leader and trailer pointer variables will be assigned into the Node* lvalues ptr1 and ptr2.
Node* ptr1 = leader;
Node* ptr2 = trailer;
The issue is that ptr1 and ptr2 are independent local variables inside the function. Initially, they point to the same place as the actual argument pointers. However, my function moves some nodes, and at the end of the function, the values of ptr1 and ptr2 are changed. I want these changes to also be in the original variables leader and trailer, just like references. So even when ptr1 and ptr2 expire, leader and trailer should go into their positions.
How would I do this? Maybe type cast the pointers into int&? Or maybe use pointers to pointers? I want to pass a pointer by reference, but I'm not sure how to do that.
I want to pass a pointer by reference, but I'm not sure how to do that.
For this, consider the following snippet
#include <iostream>
void test(int*& t)
{
t = nullptr;
}
int main()
{
int* i = new int(4);
test(i);
if (i == nullptr)
std::cout << "I was passed by reference" << std::endl;
}
in which is is passed by reference to test, where it is set to nullptr and the program prints: I was passed by reference.
I think this example should make clear how to pass a pointer by reference to a function.
So in your case the function signiture must change to
void LinkedList::move_five_nodes(Node*& ptr1, Node*& ptr2) { ... }
#include <iostream>
void test(int& ref);
int main()
{
int* pointer = new int(10);
std::cout << "before" << *pointer << std::endl ;
test(*pointer);
std::cout << "after" << *pointer << std::endl;
delete pointer;
}
void test(int& ref)
{
ref = 20;
}