what happens to free()?

J

Jerry

Hi,all

I write a function to copy one memory buffer to anther with
dynamic allocationg when the destination is not large enough.
The code is below:
void DSM_CC::fillBuf(unsigned char** pdstBuf,int* pdstBufBase,int*
pdstTolalLen,char* pbufToWrite,int lenToWrite)
{
unsigned char* tmp;
int step = 256;
short allocateCnt = 10;
if(*pdstBufBase + lenToWrite > *pdstTolalLen)
{
if(!(*pdstBuf))//pdstBuf == null
{
while(allocateCnt--)
{
*pdstBuf = (unsigned char*)malloc(lenToWrite + step);
if(*pdstBuf)
break;
}
*pdstTolalLen = lenToWrite + step;
}
else
{
allocateCnt = 10;
while(allocateCnt--)
{
tmp = (unsigned char*)malloc(*pdstBufBase);
if(tmp)
break;
}
memcpy(tmp,*pdstBuf,*pdstBufBase);
//\\!realloc will make the original data lost??
realloc(*pdstBuf,*pdstBufBase + lenToWrite +
step); memcpy(*pdstBuf,tmp,*pdstBufBase);
free(tmp);
*pdstTolalLen = *pdstBufBase + lenToWrite + step;
}
}
memcpy(*pdstBuf+ *pdstBufBase,pbufToWrite,lenToWrite);
*pdstBufBase += lenToWrite;
}

when the function was invoked the third time.An exception happens
at line"free(tmp)"

Anther:Is there any way to deside if a pointer is valid or not?
For example,I use if(!(*pdstBuf)) to detect it.But we know when
a pointer declaration,the initialization value may not be NULL(that's
0).SO if(!(*pdstBuf)) will not work when an invalid pointer with value
0xccccccc(VC 6.0)

::Envir0nment: vc6.0 sp6

please why? Thx!
 
L

Lew Pitcher

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,all

I write a function to copy one memory buffer to anther with
dynamic allocationg when the destination is not large enough.
The code is below:
void DSM_CC::fillBuf(unsigned char** pdstBuf,int* pdstBufBase,int*

I hate to say it, but this isn't C code. P'haps that's why you have problems
with it. My comments below will be /as if/ you had posted C code.
pdstTolalLen,char* pbufToWrite,int lenToWrite)
{
unsigned char* tmp;
int step = 256;
short allocateCnt = 10;
if(*pdstBufBase + lenToWrite > *pdstTolalLen)
{
if(!(*pdstBuf))//pdstBuf == null
{
while(allocateCnt--)
{
*pdstBuf = (unsigned char*)malloc(lenToWrite + step);
if(*pdstBuf)
break;
}
*pdstTolalLen = lenToWrite + step;
}
else
{
allocateCnt = 10;
while(allocateCnt--)
{
tmp = (unsigned char*)malloc(*pdstBufBase);

Suspicious - casting the results of malloc() hides problems.
if(tmp)
break;
}
memcpy(tmp,*pdstBuf,*pdstBufBase);
//\\!realloc will make the original data lost??
realloc(*pdstBuf,*pdstBufBase + lenToWrite +
step); memcpy(*pdstBuf,tmp,*pdstBufBase);

You can't realloc() what you haven't malloc()ed in the first place. Is
*pdstBuf a pointer malloc()ed storage?
free(tmp);
*pdstTolalLen = *pdstBufBase + lenToWrite + step;
}
}
memcpy(*pdstBuf+ *pdstBufBase,pbufToWrite,lenToWrite);
*pdstBufBase += lenToWrite;
}

when the function was invoked the third time.An exception happens
at line"free(tmp)"

If your realloc() is fiddling with memory that wasn't malloc()ed in the first
place, it can bollix things up enough to cause malloc() or free() to fail at
some point or another.
Anther:Is there any way to deside if a pointer is valid or not?

No. Not in standard C


[snip]


- --
Lew Pitcher

Master Codewright & JOAT-in-training | GPG public key available on request
Registered Linux User #112576 (http://counter.li.org/)
Slackware - Because I know what I'm doing.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.7 (GNU/Linux)

iD8DBQFDVbWSagVFX4UWr64RApDzAJwKyIOAwulFjcePq8lWwJ2Ucwb5HQCg3zks
fRL1oyc53RvnWt2eFRnbSXE=
=Zypu
-----END PGP SIGNATURE-----
 
N

ncf

Lew said:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


You can't realloc() what you haven't malloc()ed in the first place. Is
*pdstBuf a pointer malloc()ed storage?
From the man pages for realloc()

realloc() changes the size of the memory block pointed to by
ptr to
size bytes. The contents will be unchanged to the minimum of
the old
and new sizes; newly allocated memory will be uninitialized. If
ptr is
NULL, the call is equivalent to malloc(size); if size is equal
to zero,
the call is equivalent to free(ptr). Unless ptr is NULL, it
must have
been returned by an earlier call to malloc(), calloc() or
realloc().
If the area pointed to was moved, a free(ptr) is done.
 
N

Nick Keighley

ncf said:
Lew Pitcher wrote:>
Jerry wrote:

From the man pages for realloc()

realloc() changes the size of the memory block pointed to by
ptr to size bytes. The contents will be unchanged to the minimum of
the old and new sizes; newly allocated memory will be uninitialized.
If ptr is NULL, the call is equivalent to malloc(size); if size is
equal to zero, the call is equivalent to free(ptr). Unless ptr is
NULL, it must have been returned by an earlier call to malloc(),
calloc() or realloc(). If the area pointed to was moved, a free(ptr)
is done.


so what?
 
N

ncf

Omri said:
So saying:


Is not entirely true. You can pass NULL to realloc.

Thank you. :)

I'm not too good with C at all really yet, but I did remember reading
that in response to one of my earlier questions.
 
M

Mark McIntyre

Thank you. :)

Then perhaps you should have said that.

Lew's point was, I think, that you can't realloc an object that you
didn't create with a *alloc call. NULL isn't an object.
 
M

Mark McIntyre

On 18 Oct 2005 19:26:00 -0700, in comp.lang.c , "Jerry"

(ignoring the fact that this is C++ and you should NOT BE USING MALLOC
AT ALL...)
//\\!realloc will make the original data lost??
realloc(*pdstBuf,*pdstBufBase + lenToWrite +step);

realloc calls should always use a temp buffer, then reassign to the
real one after checking the return. Otherwise, if the realloc fails
then the original data is lost and leaked.
Anther:Is there any way to deside if a pointer is valid or not?

Only by initialising it to a guard value.

foo* buff = 0xDEADBEEF;
 
J

Jerry

Thanks all again.

I checked the code again and again,though the function is not coded
with good
style, it can work.

The key is that,I use relloc() to re-allocate a STATIC memory
buf,that's *pdstBuf.
That's
I first declare a static variable in a function and pass it to the
fillBuf function then.

Enjoy --thx
 
K

Keith Thompson

Mark McIntyre said:
On 18 Oct 2005 19:26:00 -0700, in comp.lang.c , "Jerry"

(ignoring the fact that this is C++ and you should NOT BE USING MALLOC
AT ALL...)


realloc calls should always use a temp buffer, then reassign to the
real one after checking the return. Otherwise, if the realloc fails
then the original data is lost and leaked.

Yes, if by "temp buffer" you mean a pointer object. (The term
"buffer" is more likely to refer to the allocated memory.)
Only by initialising it to a guard value.

foo* buff = 0xDEADBEEF;

That's a constraint violation, since there's no implicit conversion
from the type of 0xDEADBEEF (either unsigned int or unsigned long) to
any pointer type (ignoring the special case of null pointer
constants). You can do

foo *buff = (foo*)0xDEADBEEF;

but the result could be a trap representation.
 
M

Mark McIntyre

That's a constraint violation,

Maybe I'm misreading this then:
6.3.2.3 (5) An integer may be converted to any pointer type.....
foo *buff = (foo*)0xDEADBEEF;

but the result could be a trap representation.

Which might well be what you want (certainly it would advise you it
was a bad pointer!)

(finishing the above quote)
Except as previously specified, the result is implementation-defined,
might not be correctly aligned, might not point to an entity of the
referenced type, and might be a trap representation
 
P

Peter Nilsson

Mark said:
Maybe I'm misreading this then:
6.3.2.3 (5) An integer may be converted to any pointer type.....

That discusses the conversion, Keith is talking about the simple
assignment
constraint (6.5.6.1p1).
 
K

Keith Thompson

Mark McIntyre said:
Maybe I'm misreading this then:
6.3.2.3 (5) An integer may be converted to any pointer type.....

Yes, it can be converted, but not implicitly. That's why
foo *buff = (foo*)0xDEADBEEF;
is legal but
foo* buff = 0xDEADBEEF;
is not.
Which might well be what you want (certainly it would advise you it
was a bad pointer!)

Reading a trap representation invokes undefined behavior, which may or
may not advise you of anything.
 
M

Michael Wojcik

Reading a trap representation invokes undefined behavior, which may or
may not advise you of anything.

And 0xDEADBEEF, converted to a pointer of type foo*, might result
in a pointer which is not invalid. Maybe there's a foo* at
0xDEADBEEF.

I'm not sure what the point is of having a pointer sentinel value
that's not null, but one possibility would be to create one at
runtime using malloc:

#include <stdlib.h>

static void *SentinelPtr;

void *Sentinel(void) { return SentinelPtr; }

int main(void)
{
foo *FooPtr;

SentinelPtr = malloc(1);
if (! SentinelPtr) return EXIT_FAILURE;

...
/* Set a pointer to the sentinel value */
FooPtr = Sentinel();
...
/* Check a pointer for the sentinel value */
if (FooPtr == Sentinel())
...
return 0;
}

I think that's portable, though I may be missing something.
 
K

Keith Thompson

I'm not sure what the point is of having a pointer sentinel value
that's not null, but one possibility would be to create one at
runtime using malloc:

#include <stdlib.h>

static void *SentinelPtr;

void *Sentinel(void) { return SentinelPtr; }

int main(void)
{
foo *FooPtr;

SentinelPtr = malloc(1);
if (! SentinelPtr) return EXIT_FAILURE;

...
/* Set a pointer to the sentinel value */
FooPtr = Sentinel();
...
/* Check a pointer for the sentinel value */
if (FooPtr == Sentinel())
...
return 0;
}

I think that's portable, though I may be missing something.

Or you can just take the address of a otherwise unused variable:

static char never_use_this_object;
void *Sentinel = &never_use_this_object;

Sprinkle with "const" to taste.
 
F

Flash Gordon

Keith said:
Or you can just take the address of a otherwise unused variable:

static char never_use_this_object;
void *Sentinel = &never_use_this_object;

Sprinkle with "const" to taste.

Surely that is not guaranteed to be suitably aligned for all pointer
types, so you can't portably convert it to anything other than void* or
char* ?
 
K

Keith Thompson

Flash Gordon said:
Surely that is not guaranteed to be suitably aligned for all pointer
types, so you can't portably convert it to anything other than void*
or char* ?

You're right -- and if it isn't, converting to another pointer type
(other than void* or a pointer-to-some-character-type) invokes
undefined behavior.

malloc() it is, then.

A pointer to an otherwise unused variable can still be used as a
sentinel value for a single pointer type -- which might be preferable
to a generic sentinel value anyway.
 
M

Mark McIntyre

Yes, it can be converted, but not implicitly. That's why
foo *buff = (foo*)0xDEADBEEF;
is legal but
foo* buff = 0xDEADBEEF;
is not.

See, this is what I like about CLC - every trivial example is analysed
with the anality of true geeks!
 
C

Chris Torek

I checked the code again and again,though the function is not coded
with good style, it can work.

The key is that,I use relloc() to re-allocate a STATIC memory
buf,that's *pdstBuf. That's
I first declare a static variable in a function and pass it to the
fillBuf function then.

If this means what I think it means, you should have said "though
the function is not coded with good style, it canNOT work". In
particular, the following is undefined and often causes code to
crash:

/* here T stands for any valid type, e.g.,
typedef struct foo T;
struct foo { ... };
*/
void somefunc(void) {
T buf[N]; /* for some integer constant N */
T *p = &buf[0];
T *new;
size_t newsize;

... some code to compute newsize ...
new = realloc(p, newsize);
...
}

Note also that you must capture the return value from realloc().

(Of course, since you were originally coding in C++, you should not
have been using malloc() and realloc() at all. This is what
container classes are for.)
 
M

Michael Wojcik

I'm not sure what the point is of having a pointer sentinel value
that's not null, but one possibility would be to create one at
runtime using malloc:

[snip]

I think that's portable, though I may be missing something.

Or you can just take the address of a otherwise unused variable:

static char never_use_this_object;
void *Sentinel = &never_use_this_object;

Yes, though I went with malloc for the alignment guarantee - I wanted
a sentinel pointer that was suitable to be converted to a pointer to
any object type. I'm not sure that's necessary, but it seemed like a
good idea.
Sprinkle with "const" to taste.

I thought of that too, but decided not to because there are so many
cases where a const-qualified sentinel would be awkward - if you
wanted to stick it in an array of objects of a non-const-qualified
type, for example.

--
Michael Wojcik (e-mail address removed)

I will shoue the world one of the grate Wonders of the world in 15
months if Now man mourders me in Dors or out Dors
-- "Lord" Timothy Dexter, _A Pickle for the Knowing Ones_
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top