Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Why not realloc(&ptr, ...) and free(&ptr)?

Reply
Thread Tools

Why not realloc(&ptr, ...) and free(&ptr)?

 
 
Ben Bacarisse
Guest
Posts: n/a
 
      08-05-2013
Keith Thompson <(E-Mail Removed)> writes:
<snip>
> An alternative might have been to make free() a macro that deallocates
> the memory pointed to by its argument, and then sets its argument to
> NULL. Of course you can already do that:
>
> #define FREE(p) (free(p); (p) = NULL)


I think you meant (free(p), (p) = NULL) (i.e. a comma rather than a
semicolon).

<snip>
--
Ben.
 
Reply With Quote
 
 
 
 
Joe Pfeiffer
Guest
Posts: n/a
 
      08-05-2013
"James Harris" <(E-Mail Removed)> writes:

> I cannot get my head round why calls to realloc and free do not have a
> pointer to the initial pointer passed to them as in the following if ptr had
> been returned by malloc.
>
> retcode = realloc(&ptr, new_size);
> free(&ptr);
>
> The idea being that if realloc could reallocate the space it would update
> the pointer and return true. If it could not reallocate the space it would
> leave the pointer unchanged and return false.
>
> In the case of free() the idea is that it would set the pointer to NULL.
>
> Anyone know why the above two calls were designed the way they were?


That really wouldn't help much: pointer aliasing is extremely common,
and automatically resetting one pointer to a block would still leave a
dangling pointer behind. And, of course, there would be a tendency for
novice programmers to expect all the pointers to a block to have been
reset, which wouldn't be the case.
--
"Erwin, have you seen the cat?" -- Mrs. Shroedinger
 
Reply With Quote
 
 
 
 
Shao Miller
Guest
Posts: n/a
 
      08-05-2013
On 8/5/2013 15:22, Kenny McCormack wrote:
> In article <ktosqr$f4$(E-Mail Removed)>,
> Shao Miller <(E-Mail Removed)> wrote:
> ...
>> I didn't mean to suggest that it changed the value's bits, but its meaning.

>
> We're obviously into "angels and pins" territory here - and all of us trying
> to remain catechismically correct while arguing about religious dogma.
>
> But, that said, the following ought to be good enough to demonstrate C's
> call-by-value semantics:
>
> int x = (int) p;
> free(p);
> assert(x == (int) p);
>


I think you're thinking of the subject matter of DR #260, perhaps.

http://www.open-std.org/jtc1/sc22/wg...ocs/dr_260.htm

--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily," -- Richard Harter
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      08-05-2013
Shao Miller <(E-Mail Removed)> writes:
> On 8/5/2013 14:39, Keith Thompson wrote:

[...]
>> I think there's a DR (which I can't find at the moment) that says that
>> free(p) can actually change the representation of p -- which implies
>> that the unsigned char objects that make up its representation can have
>> their values change. If I'm remembering it correctly, I'm not at all
>> convinced that that can be derived from the normative wording of the
>> standard. (Can someone else find a reference to it?)
>>

>
> DR #260?:
>
> http://www.open-std.org/jtc1/sc22/wg...ocs/dr_260.htm


Yeah, that's the one.

The committee response says, in effect, that the representation of a
pointer p can change after free(p):

Values may have any bit-pattern that validly represents them
and the implementation is free to move between alternate
representations (for example, it may normalize pointers,
floating-point representations etc.). In the case of an
indeterminate value all bit-patterns are valid representations
and the actual bit-pattern may change without direct action of
the program.

The DR mentions the issue that the bytes making up the
representation are themselves objects, and that the requirement
that "An object [...] retains its last-stored value throughout its
lifetime." implies that those bytes cannot change. The response
seems to ignore that argument.

On the other hand, I actually like the conclusion. As the DR
discusses, it permits certain optimizations

I think I would have preferred to have an explicit normative
statement added to the standard, saying that objects with
indeterminate values can have their representations change behind
the scenes.

Note that the response applies to more than just objects with
indeterminate values. If a type has multiple representations for the
same value, an object's representation can switch between those
representations -- which changes the values of the unsigned char objects
that make up its representation. This has implications for the use of
memcmp() to compare things other than byte arrays.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      08-05-2013
Ben Bacarisse <(E-Mail Removed)> writes:
> Keith Thompson <(E-Mail Removed)> writes:
> <snip>
>> An alternative might have been to make free() a macro that deallocates
>> the memory pointed to by its argument, and then sets its argument to
>> NULL. Of course you can already do that:
>>
>> #define FREE(p) (free(p); (p) = NULL)

>
> I think you meant (free(p), (p) = NULL) (i.e. a comma rather than a
> semicolon).
>
> <snip>


Yes. I thought "comma" as I was typing it, but apparently my fingers
were thinking "semicolon". I'll have to talk to them about that.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Stephen Sprunk
Guest
Posts: n/a
 
      08-05-2013
On 05-Aug-13 12:29, James Harris wrote:
> "Shao Miller" <(E-Mail Removed)> wrote in message
> news:ktok4a$c4v$(E-Mail Removed)...
>> If 'free' had a return value, then this code would ignore that
>> return value, and people with their compiler-warnings turned up
>> would have to do something like:
>>
>> (void) free(p);

>
> If the compiler warned about that wouldn't it also warn about
>
> printf("x");
>
> Having to declare
>
> (void) printf("x");
>
> would be unusual.


In fact, you will occasionally run across code like that, with the
(void)s added by someone who has their compiler (or lint) warnings
turned up a little too high.

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking
 
Reply With Quote
 
Siri Cruise
Guest
Posts: n/a
 
      08-06-2013
In article <ktnquj$6ku$(E-Mail Removed)>,
"James Harris" <(E-Mail Removed)> wrote:

> I cannot get my head round why calls to realloc and free do not have a
> pointer to the initial pointer passed to them as in the following if ptr had
> been returned by malloc.
>
> retcode = realloc(&ptr, new_size);
> free(&ptr);
>
> The idea being that if realloc could reallocate the space it would update
> the pointer and return true. If it could not reallocate the space it would
> leave the pointer unchanged and return false.
>
> In the case of free() the idea is that it would set the pointer to NULL.
>
> Anyone know why the above two calls were designed the way they were?
>
> James


You can pass lvalues into defines. Adding a few gnucisms:

#define malloc(var,n) ({ \
int n1 = n; var = (malloc)(n1); \
bool success = var || n1==0; \
success; \
})

#define realloc(var,n) ({ \
int n1 = n; typeof(var) var1 = (realloc)(var,n1); \
bool success = var1 || n1==0; \
if (success) var = var1; \
success; \
})

#define free(var) ( \
(free)(var), (var = 0) \
)
--
There but for the Grace of Slick go I.
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted.
NSA CIA Constitution patriot terrorism freedom Snowden Paid Maternity Leave
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      08-06-2013
On 08/06/2013 03:01 PM, Scott Fluhrer wrote:
> "Shao Miller" <(E-Mail Removed)> wrote in message
> news:ktocmj$u9$(E-Mail Removed)...

....
>> void func(void) {
>> long * lp;
>>
>> lp = malloc(sizeof *lp);
>> /* ... */
>> free(lp);
>> lp = NULL;
>> }
>>
>> There's not really a need to set 'lp' to a null pointer value, here, as
>> its lifetime is about to expire. You might want to for security reasons,
>> perhaps, but then it does cost time.

>
> Actually, it doesn't likely cost anything. If the compiler is even slightly
> aggressive about optimization, it will realize that lp is a dead variable
> here (no further reads), and hence will optimize the assignment out.


True. The program isn't going to waste any time executing that line of
code, because the compiler is going to spend a completely negligible
amount of time figuring that it can be dropped. On the other hand, the
author wasted his time writing that line of code, and others will waste
time reading it and puzzling over why it's there. I think the waste of
their time is far more important than the time the compiler will waste.

 
Reply With Quote
 
Shao Miller
Guest
Posts: n/a
 
      08-06-2013
On 8/6/2013 15:01, Scott Fluhrer wrote:
> "Shao Miller" <(E-Mail Removed)> wrote in message
> news:ktocmj$u9$(E-Mail Removed)...
>> On 8/5/2013 05:30, James Harris wrote:
>>> I cannot get my head round why calls to realloc and free do not have a
>>> pointer to the initial pointer passed to them as in the following if ptr
>>> had
>>> been returned by malloc.
>>>
>>> retcode = realloc(&ptr, new_size);
>>> free(&ptr);
>>>
>>> The idea being that if realloc could reallocate the space it would update
>>> the pointer and return true. If it could not reallocate the space it
>>> would
>>> leave the pointer unchanged and return false.
>>>
>>> In the case of free() the idea is that it would set the pointer to NULL.
>>>
>>> Anyone know why the above two calls were designed the way they were?
>>>

>>
>> What James Kuyper said. If you'd shared the declaration of 'ptr' in your
>> code, it might've been easier to point to. (No pun intended.)
>>
>> Also consider:
>>
>> void func(void) {
>> long * lp;
>>
>> lp = malloc(sizeof *lp);
>> /* ... */
>> free(lp);
>> lp = NULL;
>> }
>>
>> There's not really a need to set 'lp' to a null pointer value, here, as
>> its lifetime is about to expire. You might want to for security reasons,
>> perhaps, but then it does cost time.

>
> Actually, it doesn't likely cost anything. If the compiler is even slightly
> aggressive about optimization, it will realize that lp is a dead variable
> here (no further reads), and hence will optimize the assignment out.
>


Right. I forgot 'volatile' in there.

--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily," -- Richard Harter
 
Reply With Quote
 
James Harris
Guest
Posts: n/a
 
      08-07-2013

"James Kuyper" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On 08/06/2013 03:01 PM, Scott Fluhrer wrote:
>> "Shao Miller" <(E-Mail Removed)> wrote in message
>> news:ktocmj$u9$(E-Mail Removed)...

> ...
>>> void func(void) {
>>> long * lp;
>>>
>>> lp = malloc(sizeof *lp);
>>> /* ... */
>>> free(lp);
>>> lp = NULL;
>>> }
>>>
>>> There's not really a need to set 'lp' to a null pointer value, here, as
>>> its lifetime is about to expire. You might want to for security
>>> reasons,
>>> perhaps, but then it does cost time.

>>
>> Actually, it doesn't likely cost anything. If the compiler is even
>> slightly
>> aggressive about optimization, it will realize that lp is a dead variable
>> here (no further reads), and hence will optimize the assignment out.

>
> True. The program isn't going to waste any time executing that line of
> code, because the compiler is going to spend a completely negligible
> amount of time figuring that it can be dropped. On the other hand, the
> author wasted his time writing that line of code, and others will waste
> time reading it and puzzling over why it's there. I think the waste of
> their time is far more important than the time the compiler will waste.


In a tiny program that's true but consider that in a large program where the
pointer is reused as an rval as

*p

a bug might not get noticed because that pointer still refers to valid
memory. The CPU doesn't know that the memory pointed at is unused or has
been reused so it will carry out the access. Setting the pointer to NULL
allows the CPU to check that if the pointer is incorrectly used again its
use will be flagged up. The CPU will do this at absolutely no cost to the
programmer.

It is even worse if the pointer was used on the LHS of an assignment as in

*p = ...

Then the program has just overwritten some memory that could belong to
something else. Or it could have overwritten unimportant memory. Or it could
have overwritten part of a pointer chain.... The key aspect of this is that
it could have introduced one of the worst kind of bugs to track down: one
that 1) is intermittent, 2) comes and goes depending on whether the debugger
is running, or 3) only appears once the code is in production. The effect of
that *p assignment will be totally dependent on the memory layout.

All in all, setting the freed pointer to NULL is a small price to pay for
the security it offers on CPUs which can check such accesses in hardware. Of
course, if there are any other pointers to within the space they too should
be set to NULL by the programmer at the right point.

James


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
findcontrol("PlaceHolderPrice") why why why why why why why why why why why Mr. SweatyFinger ASP .Net 2 12-02-2006 03:46 PM
difference between *ptr++ and ++*ptr ? Jason C Programming 19 05-19-2005 04:50 PM
is (!ptr) or (ptr) valid way to check for NULL or NOT NULL? G Fernandes C Programming 9 02-27-2005 03:07 AM
what's the difference between delete ptr and ptr=0 -dont they accomplish the same Sid C++ 5 07-29-2004 03:42 AM
Re: realloc, need to free old ptr? Christopher Benson-Manica C Programming 4 09-01-2003 09:26 PM



Advertisments