I have a loop which tries to read data from a qml list object, here is my loop
char * argvarry[(gcps.size() * 5) + 8];
argvarry[0] = "-of";
argvarry[1] = "GTiff";
argvarry[2] = "-a_nodata";
argvarry[3] = "'0 0 0'";
argvarry[4] = "-a_srs";
argvarry[5] = a_srs;
int argc = 6;
for (int i = 0;i < gcps.size(); i++) {
argvarry[argc] = "-gcp";argc++;//gcp_values
gcppoint_ *a = qobject_cast<gcppoint_ *>(gcps.at(i).value<QObject *>());
argvarry[argc]= strdup( const_cast<char*>(QString::number(a->row()).toStdString().c_str())); argc++;
argvarry[argc] = strdup(const_cast<char*>(QString::number(a->column()).toStdString().c_str())); argc++;
argvarry[argc] = strdup(const_cast<char*>(QString::number(a->lon()).toStdString().c_str())); argc++;
argvarry[argc] =strdup( const_cast<char*>(QString::number(a->lat()).toStdString().c_str())); argc++;
}
well I tried some methods to make the above code work but none worked,
for example If I use strdup
it will work but it needs to be freed, I tried to save output of strdup
in a variable and then free it in loop, but it freed all variables. here is my try
for(int i=0;i<vl.size();i++) {
gcppoint_ *a = qobject_cast<gcppoint_ *>(vl.at(i).value<QObject *>());
char* srcX =strdup(const_cast<char*>(QString::number(a->row()).toStdString().c_str()));
char* srcY = strdup(const_cast<char*>(QString::number(a->column()).toStdString().c_str()));
char* dstX =strdup( const_cast<char*>(QString::number(a->lon()).toStdString().c_str()));
char* dstY = strdup(const_cast<char*>(QString::number(a->lat()).toStdString().c_str()));
qDebug() <<srcX<<" " <<srcY << " " <<dstX<< " " <<dstY;
argvarry[i]=srcX;
if(srcX)
free(srcX) //does not work it frees argvarry[i] too
}
//...do some thing with argvarry
free????
I noticed that all argvarry[i]
will be freed too, so I can not use them anymore. well how can I make it work, I have too free strdup
but I can not handle it. how can I change this loop and when I used argvarry
I free strup
result?
what If I change the above code to sth similar
char * srcX;
char * srcY;
char * dstX;
char * dstY;
for (int i = 0;i < gcps.size(); i++) {
argvarry[argc] = "-gcp";argc++;//gcp_values
gcppoint_ *a = qobject_cast<gcppoint_ *>(gcps.at(i).value<QObject *>());
srcX= strdup( const_cast<char*>(QString::number(a->row()).toStdString().c_str()));
srcY = strdup(const_cast<char*>(QString::number(a->column()).toStdString().c_str()));
dstX = strdup(const_cast<char*>(QString::number(a->lon()).toStdString().c_str()));
dstY =strdup( const_cast<char*>(QString::number(a->lat()).toStdString().c_str()));
argvarry[argc]=srcX;argc++;
argvarry[argc]=srcY;argc++;
argvarry[argc]=dstX;argc++;
argvarry[argc]=dstY;argc++;
}
///do things
//free(srcX);free(srcY)
char* srcX = const_cast<char*>(QString::number(a->row()).toStdString().c_str());
The problem with the above is that toStdString() returns a temporary QString object, and since the QString object is temporary, it gets destroyed at the end of the line. That means that srcX is a dangling pointer when you try to use it later.
If you absolutely need an array of char *
pointers, you'll need to make sure the data they point to remains valid for the lifetime of the array. strdup()
is one way to do that, but as you noted, it has its own difficulties, in particular you'll need to manually call free() on the strings after you're done with them, or you'll leak memory.
Another approach would be to build up a list of std::string objects first, like this:
// Build up a list of std::strings
std::vector<std::string> strsList;
strsList.push_back("-of");
strsList.push_back("GTiff");
strsList.push_back("-a_nodata");
strsList.push_back("'0 0 0'");
strsList.push_back("-a_srs");
strsList.push_back("a_srs");
for (int i = 0;i < gcps.size(); i++) {
strsList.push_back("-gcp");
strsList.push_back(QString::number(a->row()).toStdString());
strsList.push_back(QString::number(a->column()).toStdString());
strsList.push_back(QString::number(a->lon()).toStdString());
strsList.push_back(QString::number(a->lat()).toStdString());
}
// Now create an array of pointers to the data in those std::strings
// This array will remain valid for as long as strsList remains valid and unmodified
char * argvarray[strsList.size()];
for (size_t i=0; i<strsList.size(); i++) argvarray[i] = const_cast<char *>(strsList[i].c_str());