0

I have worked with the extern keyword before but now I have a really strange problem.

First of all I have my common.hh File containing the declaration of extern variables:

//some extern declarations
extern const char* PATH;

In my main.cc I do the following (ignore the cout for now):

#include "common.hh"
const char* PATH;

int main(const int argc, const char* argv[]){
PATH = somePath.c_str();
//std::cout << PATH << std::endl; //will print the correct path
//std::cout << std::string(PATH) << std::endl; //will fix the problem occuring later
//some function calls to other files where PATH is used
//... somePath still in scope ...
//... somePath is about to be destroyed
}

Now I have my other files Other.hh and Other.cc where the problem occurs: First my Other.hh

#include "common.hh"
//function declarations and some other stuff

In Other.cc the problem when accessing PATH occurs:

#include "Other.hh"
void someFunction(...){
std::cout << PATH << std::endl; //When accessing PATH here again it prints garbage

In my file Other.cc I need the const char* PATH defined in main.cc but for some reason PATH has changed. The whole problem is fixed if I do std::string(PATH) somewhere in my main.cc as seen in the cout above. I don"t get what is wrong, all my other extern variables work just fine.

EDIT: Problem is fixed for now. I just did the following in main.cc:

std::string tmp = somePath;
PATH = tmp.c_str();

I just don't understand why this fixes the problem because in theory tmp and somePath should have the same scope and should not be destroyed until after the function call in other.cc was executed. In other words: my function call in other.cc is before the scope of somePath has ended.

N. Weber
  • 135
  • 1
  • 8

2 Answers2

2

The lifetime of somePath.c_str() is bound by the somePath variable. As soon as it goes out of scope, PATH points to memory that will be re-used.

Can you make PATH a std::string instead of a char*? If not, you will have to duplicate the value of somePath.c_str() using strdup or something similar.

D.Shawley
  • 58,213
  • 10
  • 98
  • 113
  • Thank you very much. My problem was fixed by doing string tmp = somePath; PATH = tmp.c_str(); but i still don't know why because both tmp and somePath should have the same lifetime. Before somePath is out of scope I work with PATH, so why did PATH change even if somePath.c_str() was still in scope? – N. Weber Mar 14 '17 at 14:33
  • You aren't modifying `somePath` after setting `PATH` are you? `c_str` returns a raw pointer to the string's buffer. If you modify the string, then the buffer will be modified as well. – D.Shawley Mar 15 '17 at 11:46
1

c_str is a method of std::string which becomes invalid is the string is changed or destroyed. For example see details about c_str's lifetimes in this previous question.

You could either make PATH a std::string and let it make a copy or manually make a copy yourself into a char * having allocated enough memory. And then have a think about when to deallocate.


Edit - to respond to your edit

Where you have

std::string tmp = somePath;
PATH = tmp.c_str();

you claim "tmp and somePath should have the same scope" - they do not. PATH is at global scope and you have assigned it here to point to tmp's c_str().

Community
  • 1
  • 1
doctorlove
  • 18,872
  • 2
  • 46
  • 62
  • Thank you very much, my problem is fixed although I don't fully understand why. I edited my question to show that in main.cc some function call inside other.hh/cc is done where somePath should be still in scope and therefore not destroyed – N. Weber Mar 14 '17 at 14:39
  • when you assign `PATH` it will be ok, but if you try to read it later, after `tmp` has gone out of scope the pointer may well point at garbage. – doctorlove Mar 14 '17 at 15:34