我有一个发出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);
}
现在,我认为传入的这个论点是一份副本,我可以做我想做的事情&#34;。然而,重做大于10个字节的大小会使我的程序崩溃。我认为重新调整大小不到~10个字节不会因运气而崩溃。
因此,我认为我无法安全地执行此操作,应首先将其复制到新的数据缓冲区。
任何人都可以告诉我这个吗?
答案 0 :(得分:4)
为问题提供直接的答案:
Qt中的插槽只是正常的函数调用(调用它们的时候和调用它们的差异,由Qt管理),并且修改函数参数(当非const显然时)是完全有效的。当你说你得到一份副本并且你可以“做你想做的事情”时,你是对的。
在这种情况下,错误并非完全来自于您正在修改函数参数的事实。
答案 1 :(得分:2)
您展示的代码完全有效且安全,问题出在代码的其他地方。其他东西正在破坏内存,崩溃发生在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"