Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ STL queues, references and segmentation fault

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

like image 352
robert Avatar asked Jan 22 '23 20:01

robert


2 Answers

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.

like image 191
Klaim Avatar answered Jan 30 '23 09:01

Klaim


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.)

like image 21
Ken Bloom Avatar answered Jan 30 '23 09:01

Ken Bloom