How do I verify that an object being pointed by a pointer is valid
relevant code
LookupTable<Product *> table;
Product temp = *table[selection];
// if *table[selection] is not a product, program crashes...
Here is what Lookup table is:
#ifndef LOOKUPTABLE_H
#define LOOKUPTABLE_H
#include <iostream>
#include <string>
using namespace std;
#define MAXRANGE 10
template <class T>
class LookupTable
{
private:
T *aptr[MAXRANGE];
int rangeStart[MAXRANGE];
int rangeEnd[MAXRANGE];
int numRanges;
public:
T defaultValue;
bool failedRangeCheck;
std::string failReason;
// Constructor
LookupTable()
{
numRanges = 0;
defaultValue = T();
}
void addRange(int start, int end)
{
std::cout << "Created a new range... Start: " << start << " / End: " << end << endl;
failedRangeCheck = false;
//lines omitted because not working anyway
if ( !failedRangeCheck )
{
//set ranges
rangeStart[numRanges] = start;
rangeEnd[numRanges] = end;
//build new generic array with end-start+1 positions
//set pointer to point to it
aptr[numRanges] = new T[ end - start + 1 ];
numRanges++;
}
else
{
std::cout << "Range overlapped another range." << endl;
std::cout << failReason << endl;
}
}
T &operator[](int value) // Overloaded [] operator
{
for ( int i = 0; i < numRanges; i++ )
{
if ( (value >= rangeStart[i]) && (value <= rangeEnd[i]) )
{
return aptr[i][value - rangeStart[i]];
}
}
return defaultValue;
}
~LookupTable()
{
delete[] aptr;
numRanges = 0;
}
};
#endif
table is a LookupTable<Product*>. Why would it contain a pointer that isn't a Product*? That doesn't make any sense.
You shouldn't ever need to do this. The only reasons you would need to do this are if:
Through some convoluted cast you inserted a pointer to something that isn't a Product into table. The only solution to this is "don't do that."
You have a pointer to what was a Product object, but you've screwed up your object lifetime management and you destroyed the object before you were done with it. The solution to this is to use scope-bound resource management (SBRM, also called Resource Acquisition is Initialization, or RAII), which allows lifetimes to be automatically managed. Use a smart pointer container like shared_ptr/weak_ptr to facilitate this.
You put a null pointer into the table. In this case, you can either just not put null pointers into the lookup table, or check whether a pointer is null after you obtain it from the table.
Based on the code of LookupTable that you posted in a subsequent question, this question can finally be answered. (Really, I think you ought to just put that code here and remove the other question.)
table[selection] either returns a reference to an entry in the table (if the selection is found) or otherwise a reference to a default-initialized object. When LookupTable is specialized for a pointer type (such as the Product* in your code) then the default-initialized object will be a NULL pointer.
So, for the LookupTable<Product*> in your code, the expression table[selection] is either going the result in a pointer to a Product found within the table or else a NULL Product pointer.
Consequently, instead of immediately dereferencing the result of table[selection] and trying to assign it to a Product object, you should actually take the pointer value and examine it.
This would be accomplished with code similar to:
Product* result = table[selection];
if(result != NULL)
{
Product temp = *result;
// do something with temp, etc, etc
}
else
{
cout << "invalid product code" << endl;
}
You can use dynamic_cast:
if (dynamic_cast<Product *>(table[selection])) != NULL)
{
...
}
But DON'T DO THIS. If you find yourself needing to take specific action based on the runtime type of an object, you're almost certainly doing something wrong. This is what virtual functions are for.
It sounds like you need dynamic_cast. But your design also sounds suspect. Why would your collection not contain the right types ? Or, if you need to make decisions based upon the type of your object, then some form of polymorphism is what you'd most likely require.
You can use RTTI. Include the <typeinfo> header, and say:
if (typeid(*table[selection]) == typeid(Product)) { ... }
But something is really fishy here... the above statement is basically tautological, and you shouldn't need to do this at all. C++ is a strongly typed language, and so any object contained in a container of Product objects is, by definition, an instance of Product - unless you did something ridiculous, like inserting an invalid object into the container using a reinterpret_cast.
Product * temp = dynamic_cast<Product*>(table[selection]);
if (temp) {
do something
}
and GO AHEAD AND DO THIS. People will tell you not to, but don't listen to them.
Related
Context:
New to C++ here. I have a larger project where I have a classes A, B, and C.
Class A has a field with type unordered_map<int, B>.
Class B also has fields of class C which have fields of type set.
I want to mutate the B objects in the map because I don't want the overhead associated with immutability. I have tried doing this with map.find() and map.at(), but with both methods, the mapped objects are not mutated as evidenced by the behavior of subsequent calls. I didn't try indexing with [] because class B does not have a default constructor.
According to the VSCode C++ documentation (but oddly not the online docs), the pair returned by find has a copy of the value object, which is wrong for obvious reasons.
I tried using at(), which supposedly returns a reference to the value object. This results in the same issue with find(), unfortunately.
I then tried making my map with values of *B, but later, these objects would go out of scope and I assume deallocated resulting in a segmentation fault.
So I even tried changing my map to be of type <int, int> where the value is an index into a vector, which is where I found the problem to be general to containers as opposed to just maps.
I know I can do something like map.at(i) = map.at(i).funcWithSideEffects(); but I'm not ready to accept that this is the only way to do this. For a procedural language with a concept of state (i.e. not-a-fundamentally-functional language), it seems bizarre that there would be no way to mutate a value in a map or container-type field.
Long story short and minimum example:
How can I mutate objects in a container field such as a vector?
Example:
#include <string>
#include <vector>
#include <iostream>
using namespace std;
class Person
{
private:
string first;
string last;
vector<Person> children;
public:
Person(string first, string last) {
this->first = first;
this->last = last;
}
string getFirstName() {
return this->first;
}
void setFirstName(string first) {
this->first = first;
}
string getLastName() {
return this->last;
}
vector<Person> getChildren() {
return this->children;
}
void addChild(Person child) {
return children.push_back(child);
}
};
int main() {
Person p("John", "Doe");
Person child("Johnny", "Appleseed");
p.addChild(child);
Person grandchild("one", "two");
p.getChildren().at(0).addChild(grandchild);
p.getChildren().at(0).setFirstName("Mark");
cout << "Name: " << p.getFirstName() << " " << p.getLastName() << "\n";
cout << "No. Children: " << p.getChildren().size() << "\n";
cout << "Child Name: " << p.getChildren().at(0).getFirstName() << "\n";
cout << "No. Grandchildren: " << p.getChildren().at(0).getChildren().size() << "\n";
return 0;
}
Desired Output:
Name: John Doe
No. Children: 1
Child Name: Mark
No. Grandchildren: 1
Actual Output:
Name: John Doe
No. Children: 1
Child Name: Johnny
No. Grandchildren: 0
Edit:
Unfortunately, the example I created is decoupled from my original problem. Yes, the behavior that I want is that of references, which is why I was scratching my head when I used map.at(), which says it returns a reference. As described above, this is not the behavior I am observing. Leaving this solved, since I did a subpar job asking my question, and will construct a better example in a different post.
Edit 2:
Thank you to everyone who responded! I put two and two together and figured out what I was doing wrong in my map problem.
I was accessing values in my map with
B b = map.at(i);
instead of
B& b = map.at(i);
I guess the original version makes a copy instead of retaining the reference that map returns. Will make a solution post if anyone else is confused about the same thing in the future.
You returning a copy of your child with calling
vector<Person> getChildren() {
return this->children;
}
With this, your changes are done at the returned copy only. Not in the original stored inctance.
Use a reference to it and you get the
vector<Person>& getChildren() {
return this->children;
}
with this you do the changes in the stored instance.
I you want to avoid useless data copy work, you could change
void addChild(Person& child) {
return children.push_back(child);
}
That avoids creation and deletion of instances to/from the callstack.
I'm working on a C++11 program, where security is important and my task is to set to 0 the used memory after erasing it.
I have an std::map mapping from int to an std::vector of pointer to class. I have the index in std::map and a pointer to the instance I would like to delete.
The following code produces the output I want, however, I'm not sure if it's good formed code (or I would say I'm not sure if this code is ok or not).
I have 2 questions.
If the following code is ok,
It can only be compiled with -fpermissive, I don't understand the compiler error message.
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
class MyClass
{
private:
int num;
public:
MyClass(int num) { this->num = num; }
int GetNum() const { return this->num; }
};
void PrintWorkingData(const std::map<int, std::vector<MyClass*>>& working_data, int idx)
{
std::cout << "working_data[" << idx << "] is an std::vector, size: " << working_data[idx].size() << ", containing the following items: " << std::endl;
for (std::vector<MyClass*>::const_iterator it = working_data[idx].begin(); it != working_data[idx].end(); it++)
{
std::cout << "(*it)->GetNum() = " << (*it)->GetNum() << std::endl;
}
}
int main()
{
MyClass* DeleteMyClass;
std::map<int, std::vector<MyClass*>> working_data;
working_data[0].push_back(new MyClass{4});
working_data[0].push_back(new MyClass{7});
working_data[1].push_back(new MyClass{11});
// the origonal code isn't like this; let's suppose
// we stored in the DeleteMyClass pointer the MyClass pointer
// that we would like to delete
working_data[1].push_back(DeleteMyClass = new MyClass{22});
working_data[1].push_back(new MyClass{33});
working_data[2].push_back(new MyClass{1000});
PrintWorkingData(working_data, 0);
PrintWorkingData(working_data, 1);
PrintWorkingData(working_data, 2);
PrintWorkingData(working_data, 3);
// so our task is to delete DeleteMyClass object from working_data[DeleteItemIndex]
// and fill with 0 where it was stored
int DeleteItemIndex = 1;
std::vector<MyClass*>::iterator pos = std::find(working_data[DeleteItemIndex].begin(), working_data[DeleteItemIndex].end(), DeleteMyClass);
if (pos == working_data[DeleteItemIndex].end())
{
std::cout << "Error: The item does not present in the working_data" << std::endl;
}
else
{
std::fill(pos, pos + 1, 0);
working_data[DeleteItemIndex].erase(pos);
delete DeleteMyClass;
std::cout << "The object successfully deleted" << std::endl;
}
PrintWorkingData(working_data, 0);
PrintWorkingData(working_data, 1);
PrintWorkingData(working_data, 2);
PrintWorkingData(working_data, 3);
return 0;
}
Setting a pointer value to nullptr doesn't change the data it points to. Erasing an element from a vector will overwrite that element with all the later ones in the vector, leaving (in this case) a second pointer in allocated memory (beyond the size of the vector) to the last element in the vector.
To erase the memory occupied by the object that DeleteMyClass points to, you'll have to handle the object destruction and memory freeing separately. This is not necessarily easy or straightforward, as there can be nuances (exception handling, array vs. non-array forms) that need to be addressed. You should also keep in mind that it is possible to inspect the memory of a running process, and view the data you're trying to erase while the object that uses it is live.
Here are several approaches that might work for you case.
One way to do this is to manually call the destructor, clear out the memory, then free it.
DeleteMyClass->~MyClass();
memset(DeleteMyClass, 0, sizeof(*DeleteMyClass));
delete (void *) DeleteMyClass;
The cast on the delete call is necessary to avoid calling the destructor, and the number of bytes to clear uses the type of DeleteMyClass, which will be incorrect if what is pointed to is a class derived from MyClass.
Another alternative is to use placement new with an already allocated memory buffer and a custom deallocator (after manually calling the destructor) to free up the memory.
A third possibility is to use custom new and delete functions, either for this specific class or globally.
In my program, I'm trying to dereference a pointer to a struct Article, to get its id, but I'm getting "Access violation reading location 0xCCCCCCCC". I've tried many different things, local variables, backtracking the pointers back into the code, different parentheses... nothing though. I'm out of options and I can't see the problem however hard I try.
There might be an answer to this question, but access violation is much too general for me to be able to find the answer I'm looking for (also most of the questions go around arrays, which aren't my case).
Here I define a simple struct to keep my data.
struct Article {
public:
std::string id;
std::string title;
std::string text;
Article(std::string article_id, std::string article_title, std::string article_text) : id(article_id), title(article_title), text(article_text) {};
void toString();
};
Next, I use a dictionary that maps all words to the articles where they appear. The code is not done itself, but maps of words should include all the necessary pointers.
std::map<std::string, std::map<Article*, unsigned>> word_dict_;
I also keep another vector<Article> articles_ wher I keep all of them, so no null pointers should appear in the word_dict_;
Here the dictionary gets generated.
void fulltext::generateDict() {
for (Article ar : articles_) {
unsigned wordStart;
bool isBuilding = false;
string buffer = "";
for (unsigned int it = 0; it <= ar.text.size(); ++it) {
char c;
if (it < ar.text.size())
c = ar.text.at(it);
else
c = '\0';
if (isalpha(c)) {
// start or middle of word
if (!isBuilding) {
isBuilding = true;
wordStart = it;
}
buffer += c;
}
else {
isBuilding = false;
if (buffer != "") {
stringToLower(buffer); // rewrites buffer to low case
// Here I tried creating &ar just for the laughs and it works just fine.
word_dict_[buffer][&ar] = wordStart;
buffer = "";
}
}
}
}
}
Last but not least, I want to have it printed out and here the real fun starts.
void fulltext::printWordDict() {
cout << "Printing generated word dictionary: " << endl;
for (auto wordPair : word_dict_) {
cout << " \" " << wordPair.first << " \" " << endl;
cout << "There are " << wordPair.second.size() << " inputs." << endl;
for (pair<Article*, unsigned int> articlePair : wordPair.second) {
cout << (articlePair.first)->id << endl; // Here the access violation occurs
// Nothing seemingly works
// cout << articlePair.first->id; ... Access violation
// cout << (*articlePair.first).id; ... Access violation
// auto ar = articlePair.first; cout << ar->id; ... access violation
// auto ar = articlePair.first; cout << (*ar).id; ... access again
}
cout << endl;
}
cout << "Done." << endl;
}
These functions are called from within a main function fulltext::proccess() coincidentally in immediate succession. The word_dict_ is class private variable.
If there's need for any other parts of the code, just let me know, although none of the others should make any issues in this case.
for (Article ar : articles_) {
...
word_dict_[buffer][&ar] = wordStart;
...
}
Here you are storing a pointer to ar in your dictionary, however ar is destroyed at the end of its scope - when your for loop ends. So now you are storing a dangling pointer in your map, which you cannot de-reference.
Store Article objects in your map instead of Article* , or otherwise ensure the Article object lives somewhere as long as you have a pointer to it in your map.
If you have the objects live in your articles_ container, you might not need to copy it in your for loop, and instead do:
for (Article& ar : articles_) {
..
word_dict_[buffer][&ar] = wordStart;
Now you'll get a pointer to your Article object that resides within article_.
Though be aware what you do with article_ later on - if you perform operations on it that moves objects around (which can happen for many reasons depending on the container type), your pointers within word_dict_ becomes invalid.
for (Article ar : articles_)
This performs a copy of your article, as a local variable. This local variable goes out of scope as soon as the next iteration of the loop rolls around.
word_dict_[buffer][&ar] = wordStart;
Here you store a pointer to the local variable, that is valid only inside your loop.
If you can ensure that your articles will outlive your map, you can store a pointer to the articles stored in articles_. Take note, that if articles_ is a std::vector, it might get reallocated when you insert new articles into it, so storing pointers to object inside it has to be done carefully, making sure to invalidate them when the std::vector changes.
If all of the above sounds like your cup of tea, You most probably want to create a reference to the article, like so
for (Article& ar : articles_)
If the above sounds a bit too complicated, you have 2 possible approaches.
Make your word_dict_ map store Article objects by Value, instead of as pointers. Downside of this approach is that you store your articles twice, which has logical implications (changes to the article inside your map won't be reflected in the articles_ vector and vice-versa) as well as memory implications (you use double the memory)
Make your articles_ vector store std::unique_ptr<Article>. This way, you won't need to manually manage the reallocations inside your vector. You will still need to manage the case where an Article is removed from the articles_ vector, and make sure to remove it from the word_dict_ map. The downside of this approach is that it makes your class uncopiable by default (std::unique_ptr has a deleted copy constructor), which might or might not be a problem for you. If you need them to be copied, you would need to manually provide a copy ctor and copy assignment operator, as well manually implement or = default the other 3 special member functions (see Rule of 5)
I have a task to create an object Stos which would feature a heap of objects Obiekt, to which I could add things as I please.
In order to make the program better support dynamic arrays I decided to use a Vector.
The whole implementation seems to run perfectly, the returned value is completely off.
Here is an example with code:
class Obiekt {
private:
int id;
public:
Obiekt::Obiekt(int i) {
id = i;
}
void Obiekt::display() {
cout << "This object has id of: " << id << endl;
}
};
class Stos {
private:
vector < Obiekt* > stos;
public:
Stos::Stos(Obiekt n) {
add(n);
}
void Stos::add(Obiekt n) {
stos.push_back(&n);
}
void Stos::display() {
cout << endl << "===HEAP DISPLAY===" << endl;
for (int i = 0; i < stos.size(); i++) {
stos[i]->display();
}
}
};
void Zad1()
{
Obiekt obj1(5);
Obiekt obj2(23);
Stos s1(obj1);
s1.add(obj2);
s1.display();
getchar();
}
And the outcome being:
===HEAP DISPLAY===
This object has id of: -858993460
This object has id of:9805925
I'm not a cpp expert, and believe the issue is related to the stos.push_back(&n) portion, but I can't catch the moment the id gets so distorted.
It's probably a noob question, so sorry for that on start.
Any help would be amazing.
The issue with your code as O'Neil correctly explained is that you're adding the pointer to a copy of the Obiekt object. So basically, you create your object in main, and pass it to the constructor and the .add function in Stos. You then add the pointer to the vector. When the function finishes, the copy that was passed is destroyed and the pointer in your vector is dangling.
There are two ways to fix this:
1 Pass by reference
This is very simple, basically you just add an ampersand to your function parameters. For instance:
void Stos::add(Obiekt &n) {
stos.push_back(&n);
}
This will ensure that the object isn't destroyed at the end of the function
2 Don't use pointers
Another way of getting your problem to work is to avoid using pointers at all. Your vector will actually copy the contents of the Obiekt object into it. For example:
vector < Obiekt > stos; // notice how we define it without the pointer type
...
void Stos::add(Obiekt n) {
stos.push_back(n); // Creates copy which will then contain the correct value
}
The parameters Obiekt n in
Stos::Stos(Obiekt n) {
add(n);
}
void Stos::add(Obiekt n) {
stos.push_back(&n);
}
are temporary copies destroyed immediatly after each call.
You have to use a reference Obiekt & n instead, or better: by pointer Obiekt * n.
I'm reluctant to assert that the objects exist at the time display is called.
Problem(s)
According to GCC's implementation they don't.
They fall out of scope and are immediately destructed. Give "Obiekt" a non-trivial destructor and this behavior becomes obvious:
~Obiekt(){std::cout << "Bye from: " << it << std::endl;}
Secondarily, note that you shouldn't specify the class membership for functions defined within the class itself (no class_name::function_name(parameters), just function_name(parameters) )
Possible Fix
You (might) want to changing "Stos" such that:
Stos(Obiekt &n) {add(n);}
void add(Obiekt &n) {stos.push_back(&n);}
I have a class State that has a string data type called moveType. In the implementation of my code, I am calling a setter void setMoveType(string _moveType); and it's implemented with just moveType = _moveType;
When I call my getter string getMoveType() const; on an instance of State and output it to cout, nothing is displayed.
I am couting upon entering the getMoveType() function. The parameter indeed has the correct value, but it appears that it's not getting set at all.
Does anyone have any idea? I feel this is something simple/trivial in c++ that I'm just completely forgetting.
string State::getMoveType() const {
return moveType;
}
void State::setMoveType(string move_type) {
cout << "In setMoveType and param = " << move_type << endl;
moveType = move_type;
}
std::cout << vec_possibleSuccessors[i].getMoveType() << endl; // within loop;
vector<State> vec_possibleSuccessors;
if (_minState.canMoveUp()) {
up = _minState.moveUp();
up.setMoveType("UP");
up.setF(f(up));
vec_possibleSuccessors.push_back(up);
}
In the above code, _minState and up are instances of State. Also, I have made sure that my copy constructor and assignment operator have been modified to include moveType assignments.
There isn't really enough code to know for sure, but I have a guess: Either you actually assigned to a shadowed variable in the "set" function and never set the class attribute at all, or your State object has actually been destroyed and the string becomes empty (since being empty is one possible option when using destroyed memory).
Well not an answer but a short example that works the way you seem to intend this to work:
#include <string>
class State
{
private:
std::string m_moveType;
public:
State() : m_moveType( "unknown" ) {}
std::string getMoveType() const { return m_moveType; }
void setMoveType( const std::string& moveType ) { m_moveType = moveType; }
};
In your main function or were else you need a vector of States you could write this:
#include <iostream>
#include <vector>
#include "State.h"
int main()
{
std::vector< State > states;
for( int i=0; i<10; ++i )
{
State newState;
newState.setMoveType( "state" );
states.push_back( newState );
}
// do whatever you need to do....
std::vector< State >::iterator it;
std::vector< State >::iterator end = states.end();
for( it=states.begin(); it != end; ++it )
std::cout << (*it).getMoveType() << std::endl;
return 0;
}
A few remarks:
passing parameters by value like setMoveType( string s ) is not
adviseable, pass const references instead. Passing by value incurrs a
full copy of the passed object
be careful with includes and namespaces, in doubt take the extra time
to type std::... if you intend to use a feature defined in namespace
std, and never type using namespace std in a header file.
initialize private members to a sensible default and do it in the class
initializer list
I'm not sure on this either, but you appear to be storing this State in a vector. Could you post the code to how you set elements in the vector? Its important to note that you can't update an element in a vector once its inserted (unless you store a pointer to the element). Also depending upon how you call set, there may be problems.