|
||||
|
Section 17:
|
[17.11] How do I change the string-length of an array of char to prevent memory leaks even if/when someone throws an exception?
If what you really want to do is work with strings, don't use an array of char in the first place, since arrays are evil. Instead use an object of some string-like class. For example, suppose you want to get a copy of a string, fiddle with the copy, then append another string to the end of the fiddled copy. The array-of-char approach would look something like this:
void userCode(char const* s1, char const* s2)
{
char* copy = new char[strlen(s1) + 1]; // make a copy
strcpy(copy, s1); // of s1...
// use a try block to prevent memory leaks if we get an exception
// note: we need the try block because we used a "dumb" char* above
try {
...code that fiddles with copy...
char* copy2 = new char[strlen(copy) + strlen(s2) + 1]; // append s2
strcpy(copy2, copy); // onto the
strcpy(copy2 + strlen(copy), s2); // end of
delete[] copy; // copy...
copy = copy2;
...code that fiddles with copy again...
}
catch (...) {
delete[] copy; // we got an exception; prevent a memory leak
throw; // re-throw the current exception
}
delete[] copy; // we did not get an exception; prevent a memory leak
}
Using char*s like this is tedious and error prone. Why not just use an
object of some string class? Your compiler probably supplies a string-like
class, and it's probably just as fast and certainly it's a lot simpler and
safer than the char* code that you would have to write yourself. For
example, if you're using the std::string class from the standardization committee, your code might look something like this:
#include <string> // Let the compiler see std::string
void userCode(std::string const& s1, std::string const& s2)
{
std::string copy = s1; // make a copy of s1
...code that fiddles with copy...
copy += s2; // append s2 onto the end of copy
...code that fiddles with copy again...
}
The char* version requires you to write around three times more code than
you would have to write with the std::string version. Most of the savings
came from std::string's automatic memory management: in the std::string
version, we didn't need to write any code...
|
|||