From: Tim Roberts on
"bob" <robert(a)robert.org> wrote:
>
>I need to allocate a variable size struct using malloc() and then free it
>using free(). Is there a way I could wrap a pointer returned from malloc()
>in auto_ptr<>? I've used auto_ptr<> with objects of struct/class but only
>when they were allocated using new() operator. AFAIK, it is generally not
>safe to allocate with malloc() and then free with delete().

Although it's certainly good to bear this in mind as a general rule, in the
Visual C++ library, "operator new" actually calls "malloc".
--
Tim Roberts, timr(a)probo.com
Providenza & Boekelheide, Inc.
From: Ulrich Eckhardt on
Richard wrote:
> Ulrich Eckhardt <eckhardt(a)satorlaser.com> spake the secret code
> <9pn5b7-fku.ln1(a)satorlaser.homedns.org> thusly:
>
>>No, read the original posting again: The OP wants to allocate a structure
>>with a _variable_ size.
>
> Yeah, big deal. So its variable size. So its allocated by a C
> library.
>
> So what?
>
> You can still handle the acquisition and release of this resource with
> a c'tor/d'tor pair.

Yes you can, e.g. with some smart pointer that holds a pointer to such an
object, which is what the OP was asking about. No, not in auto_ptr's,
because that uses delete.

Richard, this structure is not an object as normal objects, where you simply
allocate "sizeof (type)" bytes, invoke the ctor on them and then work with
them. Rather you allocate "sizeof (type) + extra" bytes and then assume
that the array, which is the last field in the struct, has "extra" bytes.

You can not do that in the constructor/destructor, because at that time the
storage for the object was already allocated. In case you suggest using a
vector<byte> for the array in question, I believe you are missing the
point. If the OP decided it's best to use a variable-size array in a
struct, there may actually be a reason for that.

> You don't need to override operator new/delete.
>
> Do the simplest thing that could possibly work. Overriding operator
> new/delete is more complicated than is necessary.

Maybe that _is_ the simplest thing possible.

Uli

--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
From: Ulrich Eckhardt on
Ulrich Eckhardt wrote:
> bob wrote:
>> I need to allocate a variable size struct using malloc() and then free it
>> using free(). Is there a way I could wrap a pointer returned from
>> malloc() in auto_ptr<>?
>
> No, auto_ptr uses delete, which you must not use with a pointer returned
> from malloc. What I'm not sure about is whether you could override
> operators new/delete for your struct and redirect these accordingly to do
> The Right Thing(tm). I'd try asking this in comp.lang.c++.moderated.

Without claiming that this is portable, it seems to do the right thing under
GCC 4:

struct var
{
size_t len;
unsigned char content[0];
#ifdef __cplusplus
static auto_ptr<var> create(size_t len)
{
void* ptr = malloc(sizeof (var) + len);
printf("create() = %p\n", ptr);
if(!ptr)
throw std::bad_alloc();
auto_ptr<var> res(static_cast<var*>(ptr));
res->len = len;
return res;
}
auto_ptr<var> clone() const
{
auto_ptr<var> res = create(len);
memcpy(res.get(), this, sizeof (var) + len);
return res;
}
void operator delete(void* ptr)
{
printf("delete(%p)\n", ptr);
free(ptr);
}
private:
// private constructor, use create()
var(){}
// not copyable, use clone()
var(var const&);
// not assignable
var& operator=(var const&);
#endif
};


Cheers!

Uli

--
C++ FAQ: http://parashift.com/c++-faq-lite

Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
From: bob on
I think that if I introduce any C++ members in the struct then the struct
will no longer be a C struct and therefore I will not be able to cast its
pointer to an array of bytes that I can safely pass to a C routine. At the
moment it is more of a convenience issue and an attempt to avoid any mods to
existing C code.


"John H." <oldman_fromthec(a)yahoo.com> wrote in message
news:ce57327f-bdc0-4153-9692-269f971a429d(a)i10g2000yqh.googlegroups.com...
> bob wrote:
>> Thanks to everyone who replied to my post.
>>
>> It looks like I have to get rid of malloc()/free() or forget about
>> auto_ptr<> and deal with deallocating memory manually.
>>
>> For those interested, the reason that I'm using a variable length struct
>> is
>> that I receive it from a network as a stream of bytes. The first couple
>> of
>> bytes represent a header and the length of variable size data that
>> follows.
>> I have a low-level c routine that deals with assembling the packet and
>> then
>> returns it to clients. Currently the routine allocates ram for the
>> packet
>> and the client frees it. Quite often logic on the client gets a bit
>> complicated and ideally I'd like to use auto_ptr<> so I do not need to
>> worry
>> about freeing the memory allocated in the c routine.
>
> Is it a requirement that the low-level be C? One thing you might try
> is redoing your struct like this:
>
> struct structA {
> int x;
> int y;
> std::vector<unsigned char> data;
> };
>
> You can then return this structure by value to the client code. When
> they are done using it, the memory will clean itself up. If you don't
> like to return by value, you could put the structA into an auto_ptr
> and return that:
>
> structA read_socket(socket & sock)
> {
> unsigned char buffer[256] = {0};
> buffer << sock;
> structA packet;
> packet.data.insert(data.begin(), buffer, buffer+255);
> return packet;
> }
>
> or
>
> std::auto_ptr<structA> read_socket(socket & sock)
> {
> unsigned char buffer[256] = {0};
> buffer << sock;
> std::auto_ptr<structA> packet(new structA);
> packet->data.insert(data.begin(), buffer, buffer+255);
> return packet;
> }
>
> Also as Richard said, you could leverage a constructor/destructor into
> the structA to simplify the interface even more.


From: Richard on
[Please do not mail me a copy of your followup]

Tim Roberts <timr(a)probo.com> spake the secret code
<k012u5dskrsfo1ac7ug0n875bfnig1esn3(a)4ax.com> thusly:

>Although it's certainly good to bear this in mind as a general rule, in the
>Visual C++ library, "operator new" actually calls "malloc".

There is nothing in the C++ standard that says this must be the case,
however. Its an implementation detail. You shouldn't depend on it.

Also, array new/delete does more than just call malloc/free.

It is an error to call free on memory allocated with new.

It is an error to call delete on memory allocated with malloc.

Don't write code that "works by accident".
Write code that "works by design".
--
"The Direct3D Graphics Pipeline" -- DirectX 9 draft available for download
<http://legalizeadulthood.wordpress.com/the-direct3d-graphics-pipeline/>

Legalize Adulthood! <http://legalizeadulthood.wordpress.com>
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4
Prev: Reversing 2nd order deep std::vector
Next: Visual C++ 2010