开发者

Is something wrong with wrapper classes for C string functions?

开发者 https://www.devze.com 2023-03-25 23:56 出处:网络
I have some C++ code written in C-style. For some reasons I can\'t use C++ string and IO libraries, so for strings handling I should use only functions like sprintf, itoa, etc.

I have some C++ code written in C-style.

For some reasons I can't use C++ string and IO libraries, so for strings handling I should use only functions like sprintf, itoa, etc.

I want to replace C-style which requires temporary buffers char buf[12]; itoa(x, buf, 16); set_some_text(buf);

by the following code

class i2a
{
public:
    explicit i2a(int value) { ::sprintf(buf, "%d", value); }
    operator const char* () const { retu开发者_StackOverflow社区rn buf; }
private:
    char buf[12];
};

// usage:
set_some_text(i2a(x));

(Such classes can be written for char<->wchar_t convertions, etc.)

I see some cases when such classes will be dangerous: For example, one can write

const char* someMeaningfulName = i2a(x);
// the right code should be i2a someMeaningfulName(x); or i2a someMeaningfulName = i2a(x);
set_some_text(someMeaningfulName);

In more complex case, a function which accepts text will not copy it, but will save pointer to it somewhere. For example it may be

class Foo { .... const char* p; };
Foo f(const char* text) { ... foo.p = text; return foo; }

it can be really unobvious, unlike const char* variable.

Is there a way to make such classes more secure?


Upd: why not std::string, boost::lexical_cast, boost::format, etc :

The code should work when compiled with -fno-except (C++ exceptions disabled - no throw, no stack unwinding). Also it should keep working on low memory conditions.

std::string, streams uses heap-allocated memory and at least throws bad_alloc.

When we have no free heap memory, usually we still have some kilobytes of stack (for example to write to user that we are out of memory and then make proper cleanup).


ATL and MFC String Conversion Macros are also written in this way. Calling the constructor directly like i2a(x) will create a temporary object that will live until the function to which it is passed is complete. So here: do_some(i2a(x)), the temporary object will be there until do_some() is complete.

Refer the Example section (example 2) of this msdn document

Here,

const char* someMeaningfulName = i2a(x);
set_some_text(someMeaningfulName);

This will not work as, the temporary object will be freed on the first statement itself. someMeaningfulName will be garbage. If you feel that as lack of security, all I can say is:

That's how Microsoft does it!


You will always get somewhere into troubles if you use const char* for your local variables. You will have the same with const char* someMeaningfulName = std::string("foo").c_str();

If you can you should declare your local variable like this :

i2a someMeaningfulName(x);
set_some_text(someMeaningfulName);

You can also consider adding a copy constructor to i2a to avoid sharing the buffer between two instances.

0

精彩评论

暂无评论...
验证码 换一张
取 消