在Qt中修改槽函数中的参数是否安全?
Is it safe to modify an argument from in a slot function in Qt?
我有一个信号,发出一个std::vector<uint8_t>
,其中包含一个数据负载(缓冲区)。
然后在接收对象中,我有一个插槽,它接受一个参数std::vector<uint8_t> data
然后我试着解码这个数据。我要做的一件事是删除填充,例如:
void receive_slot(std::vector<uint8_t> data)
{
// Remove padding
if (data.size() > 20)
data.resize(data.size() - 20);
}
现在,我认为传入的参数是一个副本,我可以"做我想做的"。但是,如果重新设置大于10字节的大小,我的程序就会崩溃。我假设调整小于~10字节的大小不会使它崩溃,这只是运气。
因此,我认为我不能安全地这样做,应该首先将它复制到一个新的数据缓冲区。
关于这一点,谁能给我点化一下吗?提供对问题的直接回答:
槽在Qt只是正常的函数调用(何时和与它们被调用的参数是不同的,由Qt管理),它是完全有效的修改函数参数(当非const明显)。你说给你一份拷贝,你可以"用它做你想做的事",这是对的。
在这种情况下,错误并不纯粹是因为您修改了函数参数。
您显示的代码是完全有效和安全的,问题在代码的其他地方。其他东西正在破坏内存,而崩溃纯粹是偶然发生在receive_slot中。验证这一点真的很容易:你应该在问SO问题之前把下面的最小测试用例放在一起。
适合我。
#include <vector>
#include <QObject>
#include <QCoreApplication>
#include <QAtomicInt>
QAtomicInt n = 0;
class Object : public QObject {
Q_OBJECT
public:
Q_SIGNAL void source(const std::vector<uint8_t> &);
Q_SLOT void sink(std::vector<uint8_t> data) {
// Remove padding
if (data.size() > 20)
data.resize(data.size() - 20);
n.fetchAndAddOrdered(1);
}
};
Q_DECLARE_METATYPE(std::vector<uint8_t>)
int main(int argc, char ** argv)
{
QCoreApplication a(argc, argv);
qRegisterMetaType<std::vector<uint8_t> >();
Object src, dstD, dstQ;
const int N = 1000000;
// note elision of const & from the parameter types
dstD.connect(&src, SIGNAL(source(std::vector<uint8_t>)),
SLOT(sink(std::vector<uint8_t>)));
dstQ.connect(&src, SIGNAL(source(std::vector<uint8_t>)),
SLOT(sink(std::vector<uint8_t>)), Qt::QueuedConnection);
for (int i = 0; i < N; ++i) {
std::vector<uint8_t> v;
v.resize(qrand() % 100);
emit src.source(v);
}
a.processEvents();
Q_ASSERT(n.loadAcquire() == (2*N));
return 0;
}
#include "main.moc"
相关文章:
- 在C++中,使用带有 std::optional 参数的函数<T>来表示可选参数是否有意义?
- 如何检查给定的参数是否为 cv::noArray()?
- 如果返回 -1,时间() 的参数是否被修改?
- C++中大多数/所有 setter 函数的参数是否应该写为常量引用?
- 检查两个模板参数是否相同
- 空函数的参数是否加载到缓存中?
- 使用 lambda 作为构造函数参数是否需要C++ 17?
- 了解'this'或其他参数是否为右值
- const-ref传递的模板化参数是否经过优化,以便在足够小时按值传递
- shared_ptr构造函数参数是否应按值传递
- 如何检查模板参数是否为给定值?
- 使用聚合初始化模拟默认函数参数是否存在任何陷阱?
- 在对象序列化期间添加额外参数是否有更好的方法?
- 通过 ssh 发送参数.是否有非阻塞输入函数?
- 如何检查运算符 != 模板参数是否存在 C++ 17?
- 常量引用函数参数:是否可以禁止临时对象?
- 如何检查模板参数是否为 std::variant?
- 是否可以确定函数的参数是否已签名或无符号,以实现可能性超载函数
- 移动 l 值参考参数是否是一种不好的做法?
- 显式指定通用 lambda 的 operator() 模板参数是否合法?