Hi Carlos.
I assume that with string you mean std::string.
1) auto_ptr does causes memory leaks if used with arrays. You should
use instead use boost::scoped_array (see www.boost.org). Boost could
be a headcahe to compile if you do not have command line experience.
Fortunately scoped_array and the other types of smart pointers it
offers do not need to be compiled (are temaplate classes, i.e. header
file only)
2) it is more efficient to pass the return string as argument,
otherwise memoery allocation will be duplicated (although some
compilers are better than that")
string f()
{
string g( "xxx" ); // here allocates memory in g's buffer
return g; // here g is destroyed, and the object which
receives 'f' still need to allocate memory
}
is less efficient than
string& f( string& g)
{
g = ( "xxx" );
return g;
}
3) Do you know in advance the size of the buffer you want to allocate?
If yes, than I would not use new at all. Allocate memory from the heap
is "bad" (very inefficient). I would use the stack instead.
string& f( string& g)
{
char result[ BUFFERSIZE ]; // allocate memory on the stack is
way faster
int length = call_c_function (result, .... );
g = result; // assuming results contaiing a null terminating
caracter, otherwise you need to work a little bit harder
return g;
}
4) If you do not know in advance the size of the buffer:
string& f( string& g, size_t buffer_size )
{
char result = new char [ buffer_size ];
int length = call_c_function (result, .... );
g = result; // assuming results contaiing a null terminating
caracter, otherwise you need to work a little bit harder
delete result[];
return g;
}
Solution (3) is efficient robust
Solution (4) is efficient, but there is risk of memory leak. If inside
call_c_function a C++ exception is generated via a callback handler,
as it is normally done with C libraries, than result will never be
deallocated. To prevent this, you should use boost::scoped_array, as
in (5)
5)
string& f( string& g, size_t buffer_size )
{
boost::scoped_array<char> result ( new char[ buffer_size ] );
int length = call_c_function (result, .... );
g = result; // assuming results contaiing a null terminating
caracter, otherwise you need to work a little bit harder
// no need to delete
return g;
}
On Apr 17, 7:43 pm, Carlos Moreno <cm_n...@[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.
>
> Thanks for any comments,
>
> Carlos
--
[ See http://www.gotw.ca/resources/clcm.htm
for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


|