c++ STL 队列、引用和分段错误

发布于 2024-09-08 04:02:41 字数 1362 浏览 2 评论 0原文

通过将 java 程序转换为 c++ 来学习 C++ 的新手。以下代码在执行时会导致分段错误 (SIGSEGV)。

//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;
    }
}

突出显示了对上述代码修复分段错误问题的更改(<====):

//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;
    }
}

给出了什么?我仍在尝试理解引用和指针

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一梦浮鱼 2024-09-15 04:02:41
pagesBuffer.pop();

此行使您的参考无效。

请记住,标准容器使用的是值,而不是“引用”,因此当您使用对它的引用添加对象时,实际上您在容器中添加了该对象的副本。

然后使用 pop() 销毁该对象,使指向它的任何引用或指针无效。

也许您应该存储(共享)指针而不是对象。

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.

醉生梦死 2024-09-15 04:02:41

引用(也是指针)指向某处的一段数据。当您拥有返回引用的 getWebPage() 版本时,该引用指向pagesBuffer 内的一段数据。之后当您运行 pop() 时,您从队列中删除了该项目,从而删除了它的内存,但您的引用仍然指向它,因此它是一个悬空引用。

当您修改代码以按值返回时,您复制了要返回的对象,因此即使在运行 pop() 之后,这些副本仍然存在。

(C++ 与 Java 不同,Java 中的引用可以防止对象被删除——您必须自己管理它。)

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

老旧海报 2024-09-15 04:02:41

如果你想在队列中存储值,你的代码需要更改:

WebPage  CrawlerQueue::getWebPage() {
    if (pagesBuffer.size() > 0) {
        WebPage  page = pagesBuffer.front();
        pagesBuffer.pop();
        return page;
    } else
        throw "Web pages queue is empty!";
}

当使用 C++ 时,你需要对值、引用和指针之间的差异有一个非常清晰的概念。您还应该意识到,适用于 Java 的编码风格极不可能适用于 C++——这两种语言除了一些细微的语法相似之处之外几乎没有任何共同点。

另外,永远不要编写这样的代码:

void PageParser::extractLinks(){ 
    try {
        WebPage &  page =  crawlerqueue.getWebPage();
    }catch (const char * error) {
       return;
    }
}

默默地吞下异常总是一个非常糟糕的主意,因为(通常)在抛出站点附近捕获异常。

If you want to store values in the queue, your code needs to be changed:

WebPage  CrawlerQueue::getWebPage() {
    if (pagesBuffer.size() > 0) {
        WebPage  page = pagesBuffer.front();
        pagesBuffer.pop();
        return page;
    } else
        throw "Web pages queue is empty!";
}

When using C++ you need to have a very clear idea in your head about the differences between values, references and pointers. You should also be aware that it is extremely unlikely that a coding style that works in Java will work in C++ - the two languages have almost nothing in common except for some trivial syntactic similarities.

Also, never write code like this:

void PageParser::extractLinks(){ 
    try {
        WebPage &  page =  crawlerqueue.getWebPage();
    }catch (const char * error) {
       return;
    }
}

Silently swallowing exceptions is always a very bad idea, as (normally) is catching very near the throw site.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文