C++ Qt:在默认浏览器中打开带有目标的链接,而不泄漏内存

C++ Qt:在默认浏览器中打开带有目标的链接,而不泄漏内存,c++,qt,memory-leaks,qwebview,C++,Qt,Memory Leaks,Qwebview,通过互联网搜索,我遇到了很多方法,大多是非功能性的、非特定的或部分功能性的,用QWebView和打开URL来做各种事情 在多次咒骂之后,我终于找到了一个例子来做我想做的事情,那就是正常打开普通链接,并在外部浏览器中打开任何请求新窗口的内容;然而,有一个障碍。它会泄漏内存,因为我创建了一堆额外的webview,在进程退出之前不会清理这些视图。如何在不泄漏内存的情况下执行此操作 请原谅我对Qt的二年级理解。目前我只使用了几个小时 SSCCE: test.hpp 编译并运行 由于这是内置函数,因此不应

通过互联网搜索,我遇到了很多方法,大多是非功能性的、非特定的或部分功能性的,用
QWebView
和打开URL来做各种事情

在多次咒骂之后,我终于找到了一个例子来做我想做的事情,那就是正常打开普通链接,并在外部浏览器中打开任何请求新窗口的内容;然而,有一个障碍。它会泄漏内存,因为我创建了一堆额外的
webview
,在进程退出之前不会清理这些视图。如何在不泄漏内存的情况下执行此操作

请原谅我对Qt的二年级理解。目前我只使用了几个小时

SSCCE:

test.hpp 编译并运行
由于这是内置函数,因此不应存在任何内存泄漏。

在外部浏览器中呈现页面后,视图似乎变得无用。 您可以使用deleteLater()将ExternalWebView安排为删除:

稍后删除测试:

Window
ExternWebView
1 ExternWebView: 68
ExternWebPage
2 ExternWebView: 74
3 ExternWebView: 75
1 ExternWebPage: 43
2 ExternWebPage: 43
3 ExternWebPage: 43
4 ExternWebPage: 43
5 ExternWebPage: 43
Destroy Window
ExternWebView
1 ExternWebView: 68
ExternWebPage
2 ExternWebView: 74
3 ExternWebView: 75
4 ExternWebView: 52
Destroy ExternWebView
Destroy ExternWebPage
Destroy Window

程序中没有泄漏,因为qt内存管理系统将处理堆上创建的对象

首先,要使视图对象成为页面对象的父对象。这意味着当视图对象被销毁时,页面对象将被删除

其次,由于视图没有父视图,因此始终会得到一个窗口。当您关闭窗口或结束程序时,它将被释放。这就是为什么我说它将由qt的内存管理系统来处理


现在,当您使用内存探查器程序(如valgrind)运行您的程序时,可能会出现泄漏,这可能是真实的泄漏,也可能不是真实的泄漏。你需要识别并过滤掉它们。

你怎么知道有泄漏?我不知道!我只是怀疑。我不太明白Qt是如何工作的,但我正在更新一个对象,然后把它扔掉。如果答案是“没有泄漏,别傻了。”你可以用某种方式备份,那么我会接受。你有没有尝试过查找内存泄漏,比如valgring(如果你在linux下)?不管怎么说,m_web是这样做的,它永远不会被删除。您应该在构造函数中指定父级。@Jepessen,我假设在valgrind中永远不会将内存标记为泄漏,因为Qt的库仍然保留在它们上面。保留指向它们的指针,然后手动请求删除它们会向控制台发出非致命错误。我只是不太明白如何正确地去除它们,或者是否有更好的方法来避免问题的发生。抱歉,如果不清楚,这不是我认为它正在泄漏内存的原因。我认为它会泄漏内存的原因是我正在创建一个QWebView并应用一个QWebPage,返回它们,然后不使用或显示它们,拒绝了导航请求。因此,对于我在应用程序中单击的每一个新链接,该程序只会保存另一个不可见的QWebView副本。谢谢。我想这正是我需要的。我以前尝试过类似的事情,但遇到了一个问题,它给了我一个错误。我今天无法测试,但明天下午,我会试一试,接受这个答案,如果可行的话,申请赏金。更新一下,最近事情对我来说太疯狂了,我今天要试试这个。抱歉耽搁了。呃,我实际上还没有机会测试这个,但我没有欺骗你,而是继续奖励了你。我相信它会起作用的。
QT += core gui network webkitwidgets widgets

TEMPLATE = app
TARGET = test
INCLUDEPATH += .

CONFIG += c++11

# Input
SOURCES += test.cpp
HEADERS += test.hpp
qmake test.pro
make
./test
QDesktopServices::openUrl(QUrl("http://stackoverflow.com/"));
#include <iostream>

#include <QApplication>
#include <QGridLayout>
#include <QNetworkRequest>
#include <QDesktopServices>

#include <QEvent>
#include <QMainWindow>
#include <QWebView>

class ExternWebPage : public QWebPage {
    //Q_OBJECT

    public:
    ExternWebPage(QObject* parent = 0)
    :   QWebPage(parent)
    {
        std::cout << "ExternWebPage" << std::endl;
    }

    ~ExternWebPage() {
        std::cout << "Destroy ExternWebPage" << std::endl;
    }

    virtual bool event(QEvent *e) {
        static unsigned counter;
        std::cout << ++counter << " ExternWebPage: " << e->type() << std::endl;
        return QWebPage::event(e);
    }

    bool acceptNavigationRequest(QWebFrame *, const QNetworkRequest &request, NavigationType) {
        QDesktopServices::openUrl(request.url());
        return false;
    }
};


class ExternWebView : public QWebView {
    //Q_OBJECT

    public:
    ExternWebView(QWidget* parent = 0)
    :   QWebView(parent)
    {
        std::cout << "ExternWebView" << std::endl;
    }
    ~ExternWebView() { std::cout << "Destroy ExternWebView" << std::endl; }
    virtual bool event(QEvent *e) {
        static unsigned counter;
        std::cout << ++counter << " ExternWebView: " << e->type() << std::endl;
        return QWebView::event(e);
    }
};


class InternalWebView : public QWebView {
    //Q_OBJECT

    public:
    InternalWebView(QWidget* parent = 0)
    :   QWebView(parent)
    {}
    QWebView* createWindow(QWebPage::WebWindowType) {
        auto res = new ExternWebView();
        res->setPage(new ExternWebPage(res));
        res->deleteLater();
        return res;
    }
};


class Window : public QMainWindow {
    //Q_OBJECT

    public:
    Window()
    :   QMainWindow()
    {
        std::cout << "Window" << std::endl;
        auto web = new InternalWebView(this);
        web->setHtml("<div align=\"center\"><a href=\"http://www.google.com/\">Same Window</a> <a href=\"http://www.google.com/\" target=\"_blank\">New Window</a></div>");
        setCentralWidget(web);
    }
    ~Window() { std::cout << "Destroy Window" << std::endl; }

};


int main(int argc, char *argv[]) {
  QApplication a(argc, argv);
  Window w;
  w.show();
  return a.exec();
}
Window
ExternWebView
1 ExternWebView: 68
ExternWebPage
2 ExternWebView: 74
3 ExternWebView: 75
1 ExternWebPage: 43
2 ExternWebPage: 43
3 ExternWebPage: 43
4 ExternWebPage: 43
5 ExternWebPage: 43
Destroy Window
ExternWebView
1 ExternWebView: 68
ExternWebPage
2 ExternWebView: 74
3 ExternWebView: 75
4 ExternWebView: 52
Destroy ExternWebView
Destroy ExternWebPage
Destroy Window