简体   繁体   中英

free strdup output in a loop

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());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM