c++ - QT 网络崩溃
问题描述
我在访问网络请求的回复对象时收到 SIGSEGV。如果我这样做,它工作正常:
QNetworkAccessManager manager;
/**
* Main entry point.
*/
int main(int argc, char *argv[])
{
Configuration configuration;
QApplication a(argc, argv);
MainWindow w;
w.show();
QNetworkRequest * req = new QNetworkRequest(QUrl("http://localhost:5000/status/health"));
QNetworkReply * reply = manager.get(*req);
QObject::connect(reply, &QNetworkReply::finished, [&]{
QByteArray read = reply->readAll();
std::string readStr = read.toStdString();
std::cout << "Got reply: " << readStr << endl;
reply->close();
reply->deleteLater();
});
return a.exec();
}
但这确实是一个 SIGSEGV:
QNetworkAccessManager manager;
void doRequest() {
QNetworkRequest * req = new QNetworkRequest(QUrl("http://localhost:5000/status/health"));
QNetworkReply * reply = manager.get(*req);
QObject::connect(reply, &QNetworkReply::finished, [&]{
QByteArray read = reply->readAll();
std::string readStr = read.toStdString();
std::cout << "Got reply: " << readStr << endl;
reply->close();
reply->deleteLater();
});
}
/**
* Main entry point.
*/
int main(int argc, char *argv[])
{
Configuration configuration;
QApplication a(argc, argv);
MainWindow w;
w.show();
doRequest();
return a.exec();
}
所以有些东西超出了范围。我不知道是什么。所以我这样做了:
static QNetworkReply * reply;
void doRequest() {
QNetworkRequest req(QUrl("http://localhost:5000/status/health"));
reply = manager.get(req);
QObject::connect(reply, &QNetworkReply::finished, [&]{
QByteArray read = reply->readAll();
std::string readStr = read.toStdString();
std::cout << "Got reply: " << readStr << endl;
reply->close();
reply->deleteLater();
});
}
这不是 SIGSEGV。我不知道为什么不。
我对 lambdas 如何与 [&] 一起工作真的很愚蠢吗?或者 QNetworkReply 对象到底是什么?这真的是一个智能指针吗?因为它超出了范围,所以它被销毁了?
有没有人有指向从我的 GUI 中调用网络功能的正确方法的指针?我正在做这一切是为了让它在单击按钮时起作用。也许我需要自己保留回复对象并在那个 lambda 中忘记它们。我不知道。我找到的示例都是独立的,就像我的原始代码一样。
解决方案
lambda 中的 [&] 符号非常危险。特别是在异步环境中。
所以我要告诉你为什么:
QNetworkReply * reply = manager.get(*req);
QObject::connect(reply, &QNetworkReply::finished, [&]{
QByteArray read = reply->readAll();
std::string readStr = read.toStdString();
std::cout << "Got reply: " << readStr << endl;
reply->close();
reply->deleteLater();
});
您正在通过引用捕获回复指针。在作用域的末尾,回复指针被销毁,并且您有一个对垃圾的引用。
解决方案是按值捕获回复指针:
QNetworkReply * reply = manager.get(*req);
QObject::connect(reply, &QNetworkReply::finished, [reply]{
QByteArray read = reply->readAll(); // Works well, it's a fresh copy of the pointer
std::string readStr = read.toStdString();
std::cout << "Got reply: " << readStr << endl;
reply->close();
reply->deleteLater();
});
推荐阅读
- android - ListView 不显示 Firebase 数据库中的任何内容
- php - 为什么我的会话在 php 活动期间登录后 1440 秒后过期
- python - 如何在一个句子中找到甚至与python中的那些单词相反的单词
- ios - 如何在 swift 中使用属性字符串实现以下设计?
- android - Flutter:设置 newLatLngBounds 标记点击事件后第一次点击不起作用
- flutter - Socket.io 连接只工作一次
- azure - 如何从 Azure databricks 获取 python 笔记本路径?
- java - onProgressUpdate 不适用于 AsyncTask?
- node.js - 访问 Angular 路由时从节点接收 404
- javascript - 使用 proxyquire 时,Sinon 存根不工作