Question

I have a signal that emits a std::vector<uint8_t> which contains a load of data (a buffer).

Then in the receiving objects I have a slot that takes an argument std::vector<uint8_t> data

Then I try to decode this data. One of the things I have to do is remove padding, for example:

void receive_slot(std::vector<uint8_t> data)
{
    // Remove padding
    if (data.size() > 20)
        data.resize(data.size() - 20);
}

Now, I thought that this argument passed in is a copy that I can "do what I want with". However, doing a re-size of larger then ~10 bytes crashes my program. I assume that re-sizing less then ~10 bytes does not crash it only by luck.

I therefore assume that I can't safely do this and should first copy it to a new data buffer.

Can anyone enlighten me regarding this?

Was it helpful?

Solution

To provide a direct anwser to the question:

Slots in Qt are just normal function calls (when and with which arguments they're called is the difference, managed by Qt), and it's perfectly valid to modify function arguments (when non-const obviously). You're right when you say that you're given a copy and that you can do "do what you want with it".

In this case, the error doesn't purely come from the fact that you're modifying the function argument.

OTHER TIPS

The code you show is perfectly valid and safe and the problem is elsewhere in your code. Something else is corrupting the memory, and the crash happens in receive_slot by pure chance. It's really easy to verify that: you should have put together the minimal test case below before even asking your question on SO.

Works for me.

#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"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top