Reputation: 3160
FINAL EDIT:
It turned out there's no problem except I should have written ui->lineEdit_decviceName rather than ui->label_decviceName, otherwise I would never get the right input. And the check for right input is outside this function so I nearly step into infinite loop. Everybody should be aware of typo, it might hurt you.
So I try to implement a log-in process using Qt4.8, QtCreator and a 3rd-party lib(This lib is good).
In the main program, I defined a pointer of a class:
DeviceData* m_gcurrentdevicedata;
and pass it to a Login object:
m_loginandadddevice = new LoginAndAddDevice(..., m_gcurrentdevicedata, ...);
Constructor definition of this Login class:
LoginAndAddDevice(..., DeviceData* currentdevicedata, ....);
in the constructor of the Login class, I pass this pointer to another pointer of the same type:
this->logincurrentdevicedata = currentdevicedata;
After this, I assigned value to the object of this pointer:
logincurrentdevicedata = &(*it); ('it' is an iterator)
So now I assume that the variable gcurrentdevicedata in main program has the same address and value of logincurrentdevicedata in the Login object.(And I can get value from logincurrentdevicedata without error)
However, when I try to get value from gcurrentdevicedata in the main program, the whole program crashes. I can just guess the pointer logincurrentdevicedata doesn't have the same address or value with gcurrentdevicedata. But why and how can I overcome it? Many thanks in advance.
MORE DETAILS:
void LoginAndAddDevice::on_pushButton_login_clicked()
{
QString name = ui->label_decviceName->text().trimmed();
QList<DeviceData>& listDeviceDataref = *devicedatalist; //assign this pointer to a reference
int & useridref = *userID; //assign this pointer to a reference
QList<DeviceData>::iterator it;
for(it = listDeviceDataref.begin();it!=listDeviceDataref.end();++it)
{
if(((*it).getDeviceName() == name) && !name.isEmpty())
{
break;
}
}
qDebug()<<"after login button pressed "+QString::number((*it).getUsrID());
DeviceData& devicedataref = (*it); //here I assign the pointer value to a reference value
if(devicedataref.m_iuserid>=0)
{
qDebug()<<"after login button pressed, before set the value "+QString::number((*it).getUsrID());
useridref = devicedataref.getUsrID();
qDebug()<<"after login button pressed, before set the deviceinfo value "+QString::number(*userID);
m_logindeviceinfo = &(devicedataref.m_deviceinfo);
qDebug()<<"after login button pressed, before set the currentdevicedata value "+QString::number(*userID);
*logincurrentdevicedata = devicedataref; //this line leads to crash, prior code works fine
qDebug()<<"12121";
qDebug()<<"logincurrentdevicedata's user id: "+ QString::number(logincurrentdevicedata->getUsrID());
ui->pushButton_cancel->setText(tr("Ok"));
return;
}
//...
}
Upvotes: 0
Views: 141
Reputation: 8698
In modern C++ libraries like STL the below is neither guaranteed to get an address nor safe:
logincurrentdevicedata = &(*it); // ('it' is an iterator)
There is a possibility that with this expression you get an address of temporary or the collection deletes/moves an item. But yes, some container implementations / use cases may get the address of the collection item that way: again the collection needs to stay unchanged while the item consumed then.
Though there is a possibility that works but without knowing specifics of iterator and container type we cannot say that for sure. Neither the life-cycle of that container is clear. You also need to make sure that that iterator is valid and does not point to the end of its collection.
You can instead create the copy of that object:
auto it = collection.begin(); // OR can be an arbitrary iterator
if (it != collection.end())
auto val = *it; // make sure that new object is available
// if you pass an address of it to somewhere.
Or you can pass the reference to that collection to the consumer:
void consumer(std::list<T>& collection)
{
auto it = collection.begin(); // OR can be an arbitrary iterator
if (it != collection.end())
it->access(); // now it supposed to be safe
}
P.S. After the author of this question provided an example it turns out that that variable in question is in fact a pointer and the assignment is made to the actual value it points to:
*logincurrentdevicedata = devicedataref; // copying an object here
Here you 'dereferenced' the pointer and made it to point to the object and made an assignment by value. The code is still insufficient because it is not clear whether or not logincurrentdevicedata pointer contains a real address of DeviceData object.
To make it work it must satisfy:
DeviceData deviceData;
DeviceData* logincurrentdevicedata = &deviceData;
Or:
DeviceData* logincurrentdevicedata = new DeviceData;
The problem appears to be with basic C and from this point we can not be sure of other things potentially incorrect in that code. I see several other suspicious points in the code but such question is maybe only good for https://codereview.stackexchange.com/
Upvotes: 1