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.
Related
I really didn't know what to put as the title for this so ignore that. I also don't know how to describe the question so here is my issue.
#include <iostream>
#include <vector>
class ClassB {
public:
//LOOK AT THIS PART
int value;
char letter;
ClassB(char t, int v) {
letter = t;
value = v;
}
};
class ClassA {
private:
ClassB* ptr;
public:
ClassA(ClassB n) {
ptr = &n;
}
ClassB* getPtr(){
return ptr;
}
};
int main() {
std::vector<ClassA> objects;
for(int i=0;i<4;i++) {
objects.push_back(ClassA(ClassB('a',i)));
}
std::cout << "Value: " << objects[1].getPtr()->value << std::endl;
std::cout << "Letter: " << objects[1].getPtr()->letter;
return 0;
}
In this code, the output I should receive is
Value: 1
Letter: a
However I am receiving this
Value: 1
Letter
Also, if I were to declare letter before value (look at the comment in code), then the output would say
Value: 0
Letter: ☺
I'm not sure why the order I declare them in would affect anything, or why I'm getting a smiley face instead of a. Any help is appreciated, thank you!
The problem lies here:
ClassA(ClassB n) {
ptr = &n;
}
ClassB is a temporary variable that gets destructed at the end of the function. The pointer becomes invalid and the program goes nuts.
A simple and safe way to go about this, is to use an std::unique_ptr and pass parameters. unique_ptr will automatically delete ClassB when ClassA is deleted:
private:
std::unique_ptr<ClassB> ptr;
public:
ClassA(char t, int v) {
ptr = std::make_unique<ClassB>(t, v);
}
There's also just keeping a value instead of a pointer.
Consider this snippet:
#include <memory>
#include <iostream>
struct A
{
const int& getv()
{
return v;
}
int v{42};
};
struct Shared
{
Shared(std::shared_ptr<A> someA)
: intRef{someA->getv()}
{
}
const int& intRef;
};
Shared createShared()
{
auto sharedA = std::make_shared<A>();
return Shared(sharedA);
}
int main()
{
auto shared = createShared();
std::cout <<"Value of intRef " << shared.intRef;
return 0;
}
Why is there no segfault when accessing intRef in std::cout <<"Value of intRef " << shared.intRef?
Shared takes a shared_ptr<A> and stores a reference to the int in A.
The function createShared() creates a shared_ptr<A> and passes this to the constructor of Shared.
When createShared() returns, the shared_ptr<A> gets deleted.
I would have thought that any subsequent access to intRef of the object returned from createShared() will segfault, since the heap no longer holds this object.
Is my reasoning correct and is it just a coincidence that the segfault does not happen right on the spot?
In general, can you guide me to a coding guideline rule of CppCoreGuidelines where one should not take references of contents which live behind a smart pointer?
The problem is that an implicit cast of nullptr, to the second super class, of a class with multiple inheritance results (at least with LLVM 7.0.2) in an adjustment being applied to the nullptr. The pointer is now no longer null which (if null checks are being performed in the methods of the super class) can result in a crash (I guess technically undefined behaviour).
Here's a minimal example:
#include <iostream>
inline bool pointerIsNotNull(const void* ptr) { return ptr != nullptr; }
class IntValue {
public:
IntValue() { }
int getIntValue() { return pointerIsNotNull(this) ? value : 0; }
private:
int value;
};
static const char* nullptrChar = "nullptr";
class CharValue {
public:
CharValue() { }
const char* getCharValue() { return pointerIsNotNull(this) ? value : nullptrChar; }
private:
char* value;
};
class Foo : public IntValue, public CharValue {
public:
Foo() { }
double getDoubleValue() { return pointerIsNotNull(this) ? value : 0; }
protected:
double value;
};
int main(int argc, const char * argv[])
{
Foo* foo = nullptr;
std::cout << foo->getIntValue() << std::endl;
CharValue* charValue = foo;
std::cout << charValue->getCharValue() << std::endl;
std::cout << foo->getCharValue() << std::endl;
}
My question is this:
Is there a way to check for this kind of shenanigans without manually checking for nullptr before calls into a second superclass?
You know, is there an elegant way to do this (maybe in the second superclass) which would assure me that I've caught all possible examples of this behaviour?
EDIT: Yes, I know calling member functions from a nullptr isn't modern practice. I thought (until I posted this question) that it used to be accepted practice and in any case I'm constrained by standards I don't have control over. So, with the assumption that calling a member function on a nullptr will always enter the correct function, is there an elegant solution to my problem?
foo->getIntValue() is undefined when foo is the null pointer, which makes your entire program undefined.
That is, the dereferencing itself is undefined, and your program is doomed before it reaches the check.
There is no point in checking whether this is null, since a compiler is free to assume that it isn't (if it were, the program would be undefined, so the compiler can do whatever it wants).
I have some code that claims ownership of a sequence of raw pointers, and am wondering if there is an acceptable way to do this? What I'm looking for is a way to enforce the ownership in code to a greater degree. Mainly, I've been wondering whether or not my constructor should be taking a vector of unique pointers directly.
As a sidenote, once ownership has been claimed, the data is supposed to be immutable.
The code follows roughly the pattern of class X below.
#include <iostream>
#include <memory>
#include <vector>
using namespace std; // For readability purposes only
class X {
public:
const vector< unique_ptr<const int> > data; // In my case this is private
// Constructor: X object will take ownership of the data
// destroying it when going out of scope
X (vector<int*> rawData)
: data { make_move_iterator(rawData.begin()), make_move_iterator(rawData.end()) }
{ }
};
int main() {
// Illustrating some issues with claiming ownership of existing pointers:
vector<int*> rawData { new int(9) , new int(4) };
int* rawPointer = rawData[0];
{ // New scope
X x(rawData);
cout << *(x.data[0]) << endl; // Unique pointer points to 9
*rawPointer = 7;
cout << *(x.data[0]) << endl; // Unique pointer points to 7
}
cout << *rawPointer << endl; // The pointer has been deleted, prints garbage
return 0;
}
It is difficult to post an answer without detailed knowledge of your situation. But my recommendation is to attach your data to a unique_ptr as soon as it is known. Then you can move that unique_ptr into and out of vectors at will. For example:
#include <iostream>
#include <memory>
#include <vector>
using namespace std; // For readability purposes only
class X {
public:
const vector< unique_ptr<const int> > data; // In my case this is private
// Constructor: X object will take ownership of the data
// destroying it when going out of scope
X (vector<unique_ptr<const int>>&& v)
: data { std::move(v) }
{ }
};
vector<unique_ptr<const int>>
collectRawData()
{
auto rawData = {9, 4};
vector<unique_ptr<const int>> data;
for (auto const& x : rawData)
data.push_back(make_unique<int>(x));
return data;
}
int main() {
auto rawData = collectRawData();
{ // New scope
X x(std::move(rawData));
cout << *(x.data[0]) << endl; // Unique pointer points to 9
cout << *(x.data[1]) << endl; // Unique pointer points to 4
}
}
You did several misstakes.
In case of const vector< unique_ptr<const int> > data; a move iterator does make not that much sense. The reason why is, int* doesn't have a move constructor.
If you call X's constructor X (vector<int*> rawData) with vector < int* > so the copy constructor of vector < int* > gets called, but that's not what you want to.
Btw. the reason why to use move is, to avoid big memory copies. For instance std::vector < int* >: The member attribute size and the pointer to the memory location where your int*s are stored of std::vector<int*> must be copied by a move too but not the int*s self. A conclusion is that move is there to claim ownership.
If you want shared pointers like that, use std::shared_ptr. It owns a counter, which counts the ptrs which pointing to itself.
´
My Example Code:
class X
{
public:
const std::vector< std::shared_ptr< const int> > data; // In my case this is private
// Constructor: X object will take ownership of the data
// destroying it when going out of scope
X (std::vector<std::shared_ptr<int>>& rawData)
//: data(rawData)
: data(rawData.cbegin(), rawData.cend())
{ }
};
int main() {
// Illustrating some issues with claiming ownership of existing pointers:
std::vector<std::shared_ptr<int>> rawData { std::make_shared<int>(9), std::make_shared<int>(4) };
int* rawPointer = rawData[0].get();
{ // New scope
X x(rawData);
cout << *(x.data[0]) << endl; // Unique pointer points to 9
*rawPointer = 7;
cout << *(x.data[0]) << endl; // Unique pointer points to 7
}
cout << *rawPointer << endl; // The pointer has been deleted, prints not more garbage
return 0;
}
If you dont want use std::shared_ptr, you will need an GC.
I have a class. When this class is instantiated, I want the instance added to a list. When the object is deleted, I want it removed from the list.
So I give the object a shared pointer to itself. I then have a list of weak pointers to those shared pointers. When an object is created, it creates a shared pointer to itself, makes a weak pointer to that, and puts the weak pointer in a list.
When the object is destroyed, the shared pointer is as well. Whenever I try to access a member in the list, I ensure that it hasn't expired and that its use count isn't 0. Despite this, I still crash when the list member is destroyed. Why? Can I get around it? Here's my SSCCE:
#include <iostream>
#include <memory>
#include <vector>
class test
{
private:
std::shared_ptr<test> self;
public:
int val;
test(int set);
test(test ©) = delete; // making sure there weren't issues
// with a wrong instance being deleted
};
std::vector<std::weak_ptr<test>> tests;
test::test(int set):
val(set)
{
this->self = std::shared_ptr<test>(this);
tests.push_back(std::weak_ptr<test>(this->self));
}
void printTests()
{
for (auto i = tests.begin(); i != tests.end(); i++)
{
if (i->use_count() == 0 || i->expired())
{
tests.erase(i);
continue;
}
std::cout << i->lock()->val << std::endl;
}
std::cout << std::endl;
}
int main(int argc, char **argv)
{
{
test t(3);
std::cout << "First tests printing: " << std::endl;
printTests();
} // SEGFAULTS HERE
std::cout << "Second tests printing: " << std::endl;
printTests();
return 0;
}
The output of this program is as follows:
First tests printing:
3
Segmentation fault (core dumped)
Your issue is with how you are creating the self pointer:
this->self = std::shared_ptr<test>(this);
When a shared_ptr is created with this constructor, according to the documentation,
When T is not an array type, constructs a shared_ptr that owns the pointer p.
...
p must be a pointer to an object that was allocated via a C++ new expression or be 0
So the issue is that the shared_ptr is taking ownership of your stack object, so when the object gets destructed (and the shared_ptr along with it), shared_ptr is trying to delete your object that is on the stack. This is not valid.
For your use case, if you expect tests to outlive your vector, then you might be able to just store this.
I think the OP is interested in a solution to his original problem even if it uses a different method than the one he attempted. Here is a simple example of how to add an object to a global list when it is constructed, and remove it when it is deleted. One thing to remember: you must call AddList in every constructor you add to your base class. I didn't know whether you want the list to be accessible outside the class or not, so I added getter functions to return non-const iterators to the list.
class MyClass
{
private:
static std::list<MyClass*> mylist;
std::list<MyClass*>::iterator mylink;
// disable copy constructor and assignment operator
MyClass(const MyClass& other);
MyClass& operator = (const MyClass& other);
void AddList()
{
mylink = mylist.insert(mylist.end(), this);
}
void RemoveList()
{
mylist.erase(mylink);
}
public:
MyClass()
{
AddList();
}
virtual ~MyClass()
{
RemoveList();
}
static std::list<MyClass*>::iterator GetAllObjects_Begin()
{
return mylist.begin();
}
static std::list<MyClass*>::iterator GetAllObjects_End()
{
return mylist.end();
}
virtual std::string ToString() const
{
return "MyClass";
}
};
class Derived : public MyClass
{
virtual std::string ToString() const
{
return "Derived";
}
};
std::list<MyClass*> MyClass::mylist;
int main()
{
std::vector<MyClass*> objects;
objects.push_back(new MyClass);
objects.push_back(new MyClass);
objects.push_back(new Derived);
objects.push_back(new MyClass);
for (std::list<MyClass*>::const_iterator it = MyClass::GetAllObjects_Begin(), end_it = MyClass::GetAllObjects_End(); it != end_it; ++it)
{
const MyClass& obj = **it;
std::cout << obj.ToString() << "\n";
}
while (! objects.empty())
{
delete objects.back();
objects.pop_back();
}
}
This line is trouble:
tests.erase(i);
An iterator pointing to the erased element is invalid, and you can't increment it any longer. Luckily, erase returns a new iterator you can use:
auto i = tests.begin();
while (i != tests.end())
{
if (i->use_count() == 0 || i->expired())
{
i = tests.erase(i);
}
else {
std::cout << i->lock()->val << std::endl;
++i;
}
}