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)
Related
I have 2 classes:
class CCandidate {
public:
float score;
BitSet documents;
std::vector<std::vector<int> > phrases;
int cardinality;
/** For merging. */
CCandidate()
: score(0.0), documents(1), phrases(1), cardinality(0) {}
/** */
CCandidate(
std::vector<int>& phraseIndices, BitSet& documents,
int cardinality, float score) {
this->phrases.reserve(1);
this->phrases.push_back(phraseIndices);
this->documents = documents;
this->score = score;
this->cardinality = cardinality;
}
};
class PCandidate {
public:
CCandidate * topics;
float coverage;
bool selected;
bool mostGeneral;
bool mostSpecific;
PCandidate(CCandidate * c, float coverage)
: topics(c), coverage(coverage),
selected(true), mostGeneral(true), mostSpecific(true) {}
};
In another class where these classes are used I have something like this:
// ...
std::vector<std::shared_ptr<PCandidate> > phrases(mergeList.size());
for (size_t i = 0; i < mergeList.size(); i++) {
CCandidate * cc = baseTopics.at(mergeList.get(i));
std::wcout << cc->toString() << std::endl;
float coverage = cc->cardinality / result->cardinality;
std::wcout << "coverage=" << coverage << std::endl;
phrases.push_back(std::make_shared<PCandidate>(PCandidate(cc, coverage)));
std::for_each(phrases.begin(), phrases.end(),
[&](const std::shared_ptr<PCandidate>& pc) {
std::wcout << pc->toString() << " "; }); // error
}
}
anotherMethod(phrases);
// ...
Everything is fine with the CCandidate cc (for now in this verson it is a raw pointer), I can print its contents (method toString() not copied in here) and all is fine. Then I construct the PCandidate Object with the make_shared, push it into the phrases vector and when try to access that `phrases' vector to show me the contents of Pcandidate, the topics cluster I get an segmentation fault.
I could not do something like
std::wcout << ptr->topics->phrases.size() << std::endl
where ptr is a pointer to PCandidate. topics is a pointer to CCandidate containing the phrases vector.
It will give me
==10013== Invalid read of size 8
to see the size of the phrases vector in CCandidate.
I'm a little lost as I do not now where to track down the problem, sitting at this since yesterday. It might be a bloody beginners mistake. Is the lack of missing copy constructors / assignment operators? If yes how should they look like? For example copy the entire phrases vector, like a deep copy? I thought the default copy/assignment should be OK so far.
Would be great if somebody can show me the error or how to fix this! Thanks in advance for your time!
You're populating your phrases vector initially with mergeList.size() NULL shared-pointers, then pushing the real ones in after those.
std::vector<std::shared_ptr<PCandidate> > phrases(mergeList.size());
So the first mergeList.size() pointers in your vector are NULL. Lose the initial sizing.
std::vector<std::shared_ptr<PCandidate> > phrases;
If you want to reserve capacity, you can, but ultimately the shared pointers are still going to have to go through their reference counting algorithm either way. I'd skip it and just do the above.
This program is written in C++. I am trying to use a void function to expand a Line structure which consists of an integer length and a pointer to the next connected line. There is a void Expand function made to assign a line reference to the line pointer in the struct. The new line is to be double the size of the current line. With the code I am using, I get a g++ error of 'Taking address of temporary [-fpermissive]'. Could anyone suggest a way in which the function adds a valid instance of a line reference to the Line pointer nextLine?
struct Line
{
int length;
Line* nextLine;
};
Line NewLine(Line& lineRef)
{
Line newLine;
newLine.length = lineRef.length * 2;
return newLine;
}
void Expand(Line& lineRef)
{
//Error here states: Taking address of temporary [-fpermissive]
lineRef.nextLine = &NewLine(lineRef);
}
int main() {
Line line;
Expand(line);
cout << line.length << endl;
cout << line.nextLine->length << endl;
return 0;
}
You're trying to implement a linked list, but you don't understand manual memory management yet.
The short-term solution is to use std::list<Line>. There's already a solution that works, and you don't need to bother with the behind-the-scenes stuff.
The long-term solution also is to use std::list<Line>. No need to re-invent the wheel, even if you're a seasoned developer and know how to.
The problem with the line:
lineRef.nextLine = &NewLine(lineRef);
is what the compiler is telling you. You are taking the address of a temporary. What it means is that after the ; is reached, the temporary NewLine(lineRef) will be destroyed and the pointer lineRef.nextLine will be pointer to a dead object.
Update: how to make it work.
It depends on what you want to do. If what you want is to have a list then the simplest thing is using a prepacked list data structure (std::list<Line>) rather than rolling your own implementation of list.
If you really want to implement your own list, then you will need to dynamically allocate the next node (this will make the compiler happy) and you will need to add code to manage the list (proper construction of the Line object that initializes the fields, including copy-construction, destructors to manage the dynamic memory, probably some helper functions to walk the list (or iterators to be able to use algorithms...) Just don't bother and use std::list.
This one works
struct Line
{
int length;
Line* nextLine;
~Line(){delete nextLine;}
//Make copy constructor and assignment operator private
};
void Expand(Line* lineRef)
{
lineRef->nextLine = new Line;
lineRef->nextLine->length = 2*(lineRef->length) ;
}
int main()
{
Line* line = new Line;
line->length = 5;
Expand(line);
cout << line->length << endl;
cout << line->nextLine->length << endl;
delete line;
return 0;
}
For some reason when I try and read a property of a pointer to an object(GamePlayer) within an std::list (playerlist) it works at first, but when I try to access it later in another function I get a bunch of random numbers instead of the numbers for my client's socket. That was a mouthful, sorry. I hope someone could shed some light on the situation. I will include a simplified version of the defective code.
class GameRoom {
list<GamePlayer*> playerlist;
locigPort( LogicObj );
}
bool GameRoom::logicPort( LogicObj logit ) { // This is room[1]
list<GamePlayer*>::iterator it;
for (it = playerlist.begin(); it != playerlist.end(); it++){
cout << "socket numbers " << (*it)->socketno << endl;
/* (*it)->socketno gives me a bunch of random numbers,
not the socket numbers I was looking for! */
}
return true;
}
bool RoomDB::addPlayer( GamePlayer *playerpoint ) {
roomlist[1].playerlist.push_back( playerpoint );
// This adds the player object to the Gameroom object
cout << "player point " << playerpoint->socketno << " roomno: " << roomno;
// This shows everything should be ok so far
return true;
}
The most likely explanation is that you're calling addPlayer with a pointer than becomes invalid by the time you call logicPort. One possibility is that you call addPlayer with the address of an object on the stack, and the object disappears when the stack is unwound.
edit The problem is right here:
bool PlayerDB::addPlayer( int sid, GamePlayer tempplayer ) {
...
roomman.addPlayer( &tempplayer, tempplayer.roomno );
}
PlayerDB::addPlayer takes the second argument by value. This means that it gets a copy that exists for the lifetime of the method. You then take the pointer to that copy, and add it to the list. Once PlayerDB::addPlayer returns, the pointer becomes invalid.
It's hard to suggest a good fix without seeing more code. One possibility is to make PlayerDB::addPlayer take a pointer as its second argument, and make sure you don't repeat the same mistake one level up the call chain.
An even better possibility is to turn playerlist into list<GamePlayer>: from your code there doesn't appear to be any need for the list to contain pointers. This will simplify things greatly.
I'm sticking some data, wrapped with boost::any into a map in a class method getValue. Everything works fine, the data is in the map as appropriate etc etc in getValue. The second I leave getValue and try to use this data, it's no longer in the map.
This has me stumped, I'm probably forgetting to use a reference at a key spot, but I can't find it.
The relevant code is as follows:
test.c
//We don't want to actually document the timer, the user can do that if he wants to.
timeval tmp;
tmp.tv_sec = 0;
tmp.tv_usec = 0;
gettimeofday(&tmp, NULL);
getValue<timeval>(timerName) = tmp;
std::cout << tmp.tv_usec << " : " << getSingleton().globalValues.count(key) << std::endl; //Count returns 0 here, for a given key X_X
test.h
/* Grab the value of type T found while parsing. Should use checkValue first.*/
template<typename T>
static T& getValue(const char* identifier) {
//Used to ensure we have a valid value
T tmp;
//Used to index into the globalValues map
std::string key = std::string(identifier);
std::map<std::string, boost::any>& gmap = getSingleton().globalValues;
if(checkValue(identifier)) //If we have the option, set it's value
tmp = getSingleton().vmap[identifier].as<T>(); //vmap is correct, it specifies default values passed in via command line.
//We may have whatever is on the commandline, but what if
//The programmer has made modifications?
if(!gmap.count(key)) //The programmer hasn't done anything, lets register it then
gmap[key] = boost::any(tmp);
std::cout << "gmap " << key << std::endl;
std::cout << getSingleton().globalValues.count(key) << std::endl; //count returns 1 here, for a given key.
return boost::any_cast<T&>(gmap[key]);
}
...
test.h
//Map of global values, stored here instead of in OptionsHierarchy
//For ease of implementation
std::map<std::string, boost::any> globalValues;
On these lines you use vmap instead of gmap. Is that right?
if(checkValue(identifier)) //If we have the option, set it's value
tmp = getSingleton().vmap[identifier].as<T>();
Also I noticed that you're using count to check for existence of an item. Generally speaking unless you actually need the count, that will result in doing more work than find although for std::map it may be smart enough to optimize count into find. Since you want to insert if it doesn't exist and no-op when it does, just use insert as that's exactly the behavior insert will give you.
I fixed this, note how I define key in getValue as being std::string(identifier). In test.c I was defining key as sanitizeString(..) which returned a different key, obviously. Of course you guys couldn't see that so my bad.
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.