简体   繁体   中英

C++: Iterating over a string vector and using the index for putenv

I have a vector of strings which was created from parsing a config file. All the strings should be in the format key=value . I'd like to iterate over the vector, and use the putenv function to set an environment variable to the key-value pair.

The code:

for(auto it = settings.begin(); it != settings.end(); it++) {
      try {
         auto i = it - settings.begin();
         cout << i << endl;
         putenv(settings.at(i));
      } catch (...) {
         cout << "Config is not in the format key=value ... please correct" << endl;
      }
   }

This throws the error:

cannot convert ‘__gnu_cxx::__alloc_traits<std::allocator<std::basic_string<char> > >::value_type {aka std::basic_string<char>}’ to ‘char*’ for argument ‘1’ to ‘int putenv(char*)’

I'm very new to C++, and all these variable types and pointers are confusing me.

You're mixing C and C++ stuff.

  • Your vector contains C++ strings, std::string .
  • putenv is an "old" function expecting a pointer to a char buffer, ie a C-string.

Fortunately, std::string makes it easy to get one of those :

putenv(settings.at(i).c_str());
//                   ^^^^^^^^

However, there is still a problem there. putenv takes "ownership" of the buffer you give it, and expects it to last "forever". Yours won't; it'll only be there until the std::string is modified or destroyed. Not good enough!

Conventionally, we use C's strdup here to allocate a copy of the char buffer. It's then putenv 's (or the OS's) responsibility to free it later.

putenv(strdup(settings.at(i).c_str()));
//     ^^^^^^^                      ^

Since putenv is not in the C or C++ standard, but is provided by POSIX, you should check the manpages for your operating system to make sure you're using it correctly.

The error is caused by your call to putenv(), which expects a pointer to char 's. Your vector contains C++ strings (std::string)...

You can try this:

for (auto setting : settings) {

     // ... putenv() is inconsistent across compilers, so use setenv() instead...         
     std::string key = item.substr( 0, item.find_first_of( "=" ) ) ;
     std::string val = item.substr( key.length()+1 ) ;

     if ( setenv( key.c_str(), val.c_str(), 1 ) != 0 ) {
        cerr << "setenv(" << key << ',' << val << ") has failed: " << strerror( errno ) << endl;
     }
}

From what I've read, putenv should be avoided in new code, and setenv should be used, as it makes a copy of its arguments, regardless of compiler version.

( setenv is in stdlib.h)

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