can't use QVector::push_back on QUdpSocket
-
@eyllanesc oh, geez, I keep forgetting that...thanks.
Now, the QVector is actually a member variable; I need to use its contents outside of the routine this code is in. When the routine is called, it needs to clear the vector first. Do I understand that I need to call clear() and then squeeze() to avoid memory leaks? I'm using 5.14.2.
Thanks again.
-
OK, I thought I had a handle on this, but the compiler is telling me differently.
Background: my app needs to maintain a list of "usable" network interfaces (definition of usable not important here). My thought was to create a struct:
struct SockInfo { QNetworkInterface nic; QNetworkAddressEntry addr; QUdpSocket sockMulticast; QUdpSocket sockBroadcast; };
and have a QList of these as a member variable. But...when I try to assign a value to an element, I get a compiler error (for the reasons given in prior posts).
By converting the socket members to pointers, I can do this (this code is executed after the list is created):
for (it = m_socks.begin(); it != m_socks.end(); ++it) { pSockMulticast = new QUdpSocket; SockInfo *p; p = it; p->sockMulticast = pSockMulticast;
But this doesn't seem right -- I don't want a new socket; I want to alter the value of an entry in my list.
So...I guess I don't really understand this after all. Any explanations, or ideas on doing this better, are most welcome.
Thanks...
-
Hi,
In what way do you want to alter them ?
-
@SGaist one example is that the nic and addr will be set at app startup, but the sockets won't be filled in until later. Plus, if I need to add a connected socket to the struct, and that sock gets disconnected, I need to alter the stored data to reflect that.
-
@eyllanesc said in can't use QVector::push_back on QUdpSocket:
On the other hand I recommend you review your basic concepts of C++
Can you elaborate?
-
@mzimmers For example when using the copy constructor, clearly when doing
your_struct.sockMulticast = foo
you are trying to use the copy constructor since you are trying to copy thefoo
object to thesockMulticast
attribute of the structure. And as I already pointed out the QObjects are not copyable, the copyable ones are the pointers. Or what is the difference ofT
withT*
and understand that it is a pointer, and that you cannot assign aT*
toT
, norT
toT*
. -
OK, let's do this one step at a time. This is partial code from my header file:
struct SockInfo { QNetworkInterface nic; QNetworkAddressEntry addr; QUdpSocket *sockMulticast; QUdpSocket *sockBroadcast; }; class UdpSocket : public QObject { QVector<SockInfo> m_socks; }
and here's where I create an entry:
void UdpSocket::getHostAddrs() { SockInfo sockInfo; sockInfo.nic = *it_qni; sockInfo.addr = addrEntries[i]; m_socks.append(sockInfo); }
(Obviously some stuff is left out, but I think this demonstrates what I'm attempting.)
Does this look OK so far?
-
@mzimmers
Yes :)Notice that
m_socks.append(sockInfo)
copies your localSockInfo sockInfo
variable as a new element intom_socks
. That's why yourQUdpSocket
s needed to be pointers.Though if you'd like us (me) to nitpick (probably not!): reading your code I'd be surprised when I discover a class named
UdpSocket
holds an array of (pairs of)QUdpSocket
, so a whole bunch ofQUdpSocket
s. Maybe at leastUdpSockets
, orUdpSocketCollection
/SockInfoCollection
or similar, something to indicate it holds a bunch of them? Perhaps it's just me.... -
@JonB thanks for the confirmation, and I agree entirely about the unfortunate name of this class; that will get remedied.
In looking over an earlier post of mine, I think I caused some confusion about what I was originally doing. In my struct, I had converted the QUdpSocket elements to pointers; I just didn't post the code. Mea culpa.
I'm still having some difficulty; unfortunately, my VPN is down, so I can't post code right now. I'll post code when I can, but the essence is, I couldn't make a QVector of SockInfo. I had to make a QVector of Sockinfo *. Apart from seeming like an unnecessary level of indirection, it also made the iterator code uglier than farm subsidies.
Anyway, like I said, I'll post more code when I can. Thanks...
-
@JonB said in can't use QVector::push_back on QUdpSocket:
@mzimmers
My thought would be that the members ofSockInfo
you show are copyable (pointers to allQObject
s now), so I would have expectedQVector<SockInfo> m_socks;
to be OK.You're right -- that is OK; I don't know what my problem was, but it was something else (I need to quit working late at night).
Here's the code -- preliminary testing indicates it's working, but I invite all critique/comments.
struct SockInfo { QNetworkInterface nic; QNetworkAddressEntry addr; QUdpSocket *sockMulticast; QUdpSocket *sockBroadcast; }; class UdpSocket : public QObject { private: QVector<SockInfo> m_socks; } // creating the list, and populating some of the members. QList<QNetworkAddressEntry> addrs; QList<QNetworkAddressEntry>::iterator addr; addrs = nic->addressEntries(); // for each address entry for (addr = addrs.begin(); addr != addrs.end(); ++addr) { qha = addr->ip(); if (qha.protocol() == QAbstractSocket::IPv4Protocol) // currently ignoring IP6 addresses. { sockInfo = new SockInfo; sockInfo->nic = *nic; sockInfo->addr = *addr; m_socks.append(*sockInfo); break; } } // updating the list. QVector<SockInfo>::iterator sock; for (sock = m_socks.begin(); sock != m_socks.end(); ++sock) { pSockMulticast = new QUdpSocket; pSockBroadcast = new QUdpSocket; sock->sockMulticast = pSockMulticast; sock->sockBroadcast = pSockBroadcast; ...
Thanks...
-
@mzimmers
Briefly:sockInfo = new SockInfo; m_socks.append(*sockInfo);
Unless the
sockinfo
variable used here is a member variable of the class and you delete it in class destructor, or maybe you delete it in omitted code, this leaks. Thesockinfo = new SockInfo
instance is not itself being put inm_socks
withm_socks.append(*sockInfo);
, that copies it. Why do younew
yourSockInfo
s at all? If you are not intending this, you could have had:QSockInfo sockinfo; m_socks.append(sockInfo);
It's OK to use a local/stack variable which goes out of scope because
m_socks.append(sockInfo)
is storing a copy of it.Separately
sock->sockMulticast = pSockMulticast; sock->sockBroadcast = pSockBroadcast;
If you are updating, what are you doing about the
sock->sockMulticast/Broadcast
which is currently there, which itself was previouslynew
ed here & elsewhere? Maybe that's in your omitted code. -
I can see that I need to rename several variables...it seems like I actually tried to make this confusing.
I left out the code that ties all this together. Whenever the main routine is invoked, it first calls this:
void UdpSocket::cleanup() { QVector<SockInfo>::iterator it; for (it = m_socks.begin(); it != m_socks.end(); ++it) { if (it->sockMulticast->isValid()) { delete it->sockMulticast; } if (it->sockBroadcast->isValid()) { delete it->sockBroadcast; } } qDeleteAll(m_socks.begin(), m_socks.end()); m_socks.clear();
...and then calls the code that creates the list, and then calls the code that creates the QUdpSockets that go into that list. So, I think I'm good on memory leaks (but of course I could be wrong).
Your point about using a struct instead of a pointer to a struct is well-taken; I've changed that.
Thanks...
EDIT: since no one else commented on my implementation, I'm going to assume that it's tolerable. Marking thread as solved. Thanks to all who helped.