I have a function that converts a relative path (e.g. “log\crash.txt”) to the full path (e.g. “E:\Program\log\crash.txt”). The function is:
string_t GetAbsPath(string_t relPath)
{
char abs[1024];
//Get the working directory
GetCurrentDirectory(1024, abs);
#pragma warning(disable:4996)
//Add a slash and content folder
memcpy(&abs, strcat(abs, "\\content\\"), 1024);
//Append it to the relative path
memcpy(&abs, strcat(abs, relPath.c_str()), 1024);
#pragma warning(default:4996)
return abs;
}
string_t is a class I wrote, its basically a wrapper for a const char*. My problem is, (and I sort of anticipated this…) is that when the function returns, abs goes out of scope, and the string_t that gets the returned value is now empty/junk. In a situation like this, I would normally just use memcpy to copy it into a pointer that won’t go out of scope. But the issue there is, that pointer (which would be the const char* in string_t) would need to be delete[]‘d. string_t doesn’t have a destructor to begin with. I could write one and delete[] it there, but that posses another problem:
If I create a string_t like this:
string_t crash = "New[] isn't called! Ahh!";
When I go to delete[] it in the destructor, the program will crash because new[] was never called.
I could delete[] the const char* in the function that calls GetAbsPath, like this:
void LoadModel(string_t relPath)
{
string_t fullPath = GetAbsPath(relPath);
. . .
delete[] fullPath.c_str();
}
But I know that if I come back to the code later, I’ll be like “Why is that delete[] there”, or I’ll add it when it isn’t needed… and well the pointer is, there’s a lot of room for error there.
What can I do to keep that char in scope (I’m guessing this can only be done with pointers), and make sure that allocated memory gets cleaned up? There has to be a way, because std::string keeps everything clean, and it has features like concatenation, something my string_t doesn’t even have. I appreciate any help here, because I’m at a loss…
You have three choices:
1) Decide that
string_twill always own the string it points to and it will be responsible for deallocating it. Have the constructors allocate/copy.2) Decide that
string_twill never own the string it points to and code calling it will always be responsible for deallocating it if necessary.3) Decide that
string_twill support both models and will need a flag to decide whether to callfree[]or not in its destructor. Calling code will have to tellstring_twhether to allocate/copy or whether to just stash the pointer.Make sure to follow the rule of three. Or better yet, just use
std::stringwhich consistently takes option 1 and thus you can just use it without worrying.