J. Manzanero J. Manzanero - 28 days ago 10
C++ Question

C++ class member behaving as local variable

I have just started programming in C++, and I have found an awkward issue. Basically:


  • I have one class where a member is a
    char[MAX_LEN]
    containing the full path of a file.

  • I have one (
    char*
    ) that points to the name (without the full path) of the file.



When I constructed this class, I found that the (
char*
) pointer is actually pointing to a local variable inside the constructor, obtaining wrong results.

Precisely, the class is:

class File_t{
public:
char fullPath[1024];
char* name;

File_t(){}; // Default constructor
File_t(const char* fullPath_){
/* Copy the input name on fullPath */
strncpy(fullPath, fullPath_, sizeof(fullPath));

/* Auxiliary variable to remove the path */
char* auxstr=fullPath;
name = auxstr;

/* Loop to remove the path */
while(1){
auxstr = strstr(auxstr,"/");
if(auxstr){auxstr=auxstr+1; name=auxstr;}
else{break;}
}
}
};


And, for instance, the main consists in creating several instances of "File_t" and fill with several files /some/path/foo1,2,...

int main(int argc, char* argv[]){

const int N = 3;
File_t CC[N];
char fileName[100];

for ( int i = 0; i < N; i++){
sprintf(fileName,"%s%d","some/path/foo",i);
CC[i] = File_t(&fileName[0]);
}


cout << "Summary" << endl;
for (int i=0; i<N; i++) cout << "File " << CC[i].name << " in " << CC[i].fullPath << endl;


return 0;
}


The program output is:

File foo2 in some/path/foo0
File foo2 in some/path/foo1
File foo2 in some/path/foo2


That is, the name points to some local variable to the constructor. I have this problem with Apple, GNU, and Intel compilers.

PS: I know I should avoid using C-style strings in C++, but this was just made to learn C++ basics.

Answer Source

The problem in your code is a broken assignment operator (and copy constructor). In this line:

CC[i] = File_t(&fileName[0]);

you construct a temporary File_t object, then assign it to CC[i]. fullPath is an array, so all elements are copied. This is fine. But name is a pointer, so the only thing that's copied is the pointer itself. This is a problem because it still points into the fullPath of the temporary object.

At the end of this statement, the temporary object is destroyed. Now CC[i].name is an invalid pointer.

To fix this, define an appropriate assignment operator. It might do something like:

strcpy(fullPath, other.fullPath);
name = fullPath + (other.name - other.fullPath);