Newbie to C++ learning by converting a java program to c++. The following code results in a segmentation fault (SIGSEGV) when executed.
//add web page reference to pages queue (STL)
void CrawlerQueue::addWebPage(WebPage & webpage) {
pagesBuffer.push(webpage);
}
//remove and return web page reference from pages queue
WebPage & CrawlerQueue::getWebPage() {
if (pagesBuffer.size() > 0) {
WebPage & page = pagesBuffer.front();
pagesBuffer.pop();
return page;
} else
throw "Web pages queue is empty!";
}
//code that results in segmentation fault when called
void PageParser::extractLinks(){
try {
WebPage & page = crawlerqueue.getWebPage();
}catch (const char * error) {
return;
}
}
The changes to the above code that fix the segmentation fault issue are highlighted(<====):
//return a const WebPage object instead of a WebPage reference
const WebPage CrawlerQueue::getWebPage() { <====
if (pagesBuffer.size() > 0) {
WebPage page = pagesBuffer.front(); <====
pagesBuffer.pop();
return page;
} else
throw "Web pages queue is empty!";
}
//no segmentation fault thrown with modifications
void PageParser::extractLinks(){
try {
WebPage page = crawlerqueue.getWebPage(); <====
}catch (const char * error) {
return;
}
}
What gives? I'm still trying to understand references and pointers
pagesBuffer.pop();
This line invalidate your reference.
Remember that standard container works with values, not "references", so when you add an object using a reference to it, in fact you add a copy of the object in the container.
Then using pop(), you destroy this object, making any reference or pointer pointing to it invalid.
Maybe you should store (shared) pointers instead of the objects.
A reference (and also a pointer) points to a piece of data somewhere. When you had the version of getWebPage()
that returned a reference, that reference was pointing to a piece of data inside of pagesBuffer. When you ran pop()
after that, you removed that item from the queue, thereby deleting its memory, but your reference still pointed at it, so it was a dangling reference.
When you modified your code to return by values, you made copies of the object that you were returning, so the copies were still around even after you ran pop()
.
(C++ isn't like Java, where a reference keeps an object from being deleted -- you have to manage that yourself.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With