In article
<23fb7edb-4279-4002-8922-a4e156368767@[EMAIL PROTECTED]
>,
Carlos Moreno <cm_news@[EMAIL PROTECTED]
> wrote:
> Hi,
>
> I'm facing a situation where it would seem all possible solutions
> have some severe inconvenience.
>
> I'm creating a C++ wrapper for a C library; in this one function,
> I need to return a string. The underlying C library expects me
> to pass it a pointer where to put the result; that pointer needs
> to be dynamically allocated in the general case.
>
> So, my function goes more or less like this:
>
> string f()
> {
> char * result = new char [ ... ];
>
> int length = call_c_function (result, .... other
> parameters ... );
> // the function places the result string in the memory
> // pointed to by result, and it returns the length of the
> string
>
> return string (result, result + length);
> }
>
> Ok, obvious problem, the memory leak; if I get around that by
> constructing a string object first, then delete[] and then return,
> I'm being less efficient than I could (what I'm doing is part of a
> library, so efficiency *is* a concern, as I don't want to impose
> up-front an inefficiency that *may or may not* be im****tant for
> a particular application that uses the library).
>
> A presumably clean solution is to use a stock smart pointer:
>
> auto_ptr<char> result (new char [ ... ]);
> // ...
> return string (result.get(), result.get() + length);
>
> The "main" question of my post is here: would the above
> constitute undefined behaviour? I'm allocating with new[],
> but auto_ptr's destructor calls delete, and not delete[].
>
> I recall that the typical advice is: use auto_ptr for single
> objects, and vector for an array of objects --- but I don't
> want vector's constructor to initialize all characters to 0!
> I don't need that array to be initialized, and therefore I
> *do not want* to initialize it (efficiency, of course).
>
> What do I do? Would the following trick be guaranteed
> (in practical terms, that is) to be as efficient as the version
> using auto_ptr:
>
> char * result = new char [ ... ];
> // ...
> const string & ret (result, result + length);
> delete [] result;
> return ret;
>
> Would that guarantee (in practical terms) the same return
> value optimization that I would expect from the code with
> auto_ptr and the "inline return" (so to speak).
>
> Obviously, I would rather avoid having to create my own
> auto_ptr (with a delete[] in the destructor) just for this
> particular application.
In:
char * result = new char [ ... ];
Is the "..." known at compile time? If so just:
char result[...];
int length = call_c_function (result, ...);
Otherwise you might want to consider a pre-built smart pointer meant for
this very purpose. One is boost::scoped_array. My favorite is
currently in the C++0X working draft, and has a C++03 emulation here:
http://home.twcny.rr.com/hinnant/cpp_extensions/unique_ptr_03.html
unique_ptr<char[]> result(new char [...]);
int length = call_c_function (result.get(), ...);
Finally, if you want to, how about:
string result(..., '\0');
int length = call_c_function (result.data(), ...);
result.resize(length);
return result;
string isn't guaranteed to be contiguous in C++03, but it is in C++0X,
and I know of no implementation that does not already meet this
requirement. It does require you to initialize your original oversized
buffer. But it avoids a new/delete.
-Howard
--
[ See http://www.gotw.ca/resources/clcm.htm
for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


|