repeated allocation and deallocation 
Author Message
 repeated allocation and deallocation

Hi.

Consider the following code - note that sum is declared in the for
loop.

int func(/* ... */)
{
    /* declarations and statements */

    for (i=0; i < upper_limit; i++) {
        unsigned int sum = carry + value1[i] + value2[1];
        /* calculation with sum */
    }

    /* ... */

Quote:
}

Even if most actual implementations allocate all objects defined in a
given function at the entry of the function, on the abstract machine
(and some implementations) sum is allocated and deallocated repeatedly
when the for loop is executed.

Someone can claim that a benefit from the above style is the scope of
sum is limited to a logical unit related to the object. IMO, a better
style to get the same benefit is the following, even when upper_limit
is a small number:

int func(/* ... */)
{
    /* declarations and statements */

    /* comment for the following logical unit */
    {
        unsigned int sum;    /* comment for sum */

        for (i=0; i < upper_limit; i++) {
            sum = carry + value1[i] + value2[1];
            /* calculation with sum */
        }
    }

    /* ... */

Quote:
}

or using a new feature introduced by C99, mixing declarations with
code.

Of course, this might be a style-question, which can make endless
opinions. However, opinions are just opinions. I'd like to hear your
opinions.

Thanks in advance...

--

Dept. of Physics, Univ. of Seoul



Mon, 04 Apr 2005 20:03:19 GMT  
 repeated allocation and deallocation

Quote:
> Hi.

> Consider the following code - note that sum is declared in the for
> loop.

> int func(/* ... */)
> {
>     /* declarations and statements */

>     for (i=0; i < upper_limit; i++) {
>         unsigned int sum = carry + value1[i] + value2[1];
>         /* calculation with sum */
>     }

>     /* ... */
> }

> Even if most actual implementations allocate all objects defined in a
> given function at the entry of the function, on the abstract machine
> (and some implementations) sum is allocated and deallocated repeatedly
> when the for loop is executed.

To me this appears to be a QoI issue. From the standards point of
view the implementation is free to alloc/dealloc repeatedly.
Anyhow the compiler vendor will probably want his product to be
sold or at least become popular for his qualitiy and performance.
And may be for one or the other system allocation and
deallocation doesn't affect performance at all. So this probably
is exactly the reason why the standard doesn't define when
or how automatic variable have to be allocated.

Quote:

> Someone can claim that a benefit from the above style is the scope of
> sum is limited to a logical unit related to the object.

This exactly is why I'ld introduce "sum" like in your example
above.

- Show quoted text -

Quote:
> IMO, a better
> style to get the same benefit is the following, even when upper_limit
> is a small number:

> int func(/* ... */)
> {
>     /* declarations and statements */

>     /* comment for the following logical unit */
>     {
>         unsigned int sum;    /* comment for sum */

>         for (i=0; i < upper_limit; i++) {
>             sum = carry + value1[i] + value2[1];
>             /* calculation with sum */
>         }
>     }

>     /* ... */
> }

This really looks crappy, and I can't see what benefit this
should bring. If the implementation chooses to alloc/dealloc
repeatedly it may have it's reasons.

Quote:

> or using a new feature introduced by C99, mixing declarations with
> code.

> Of course, this might be a style-question, which can make endless
> opinions. However, opinions are just opinions. I'd like to hear your
> opinions.

--

"LISP  is worth learning for  the profound enlightenment  experience
you will have when you finally get it; that experience will make you
a better programmer for the rest of your days."   -- Eric S. Raymond


Mon, 04 Apr 2005 21:22:13 GMT  
 repeated allocation and deallocation

Quote:

[...]

> > IMO, a better
> > style to get the same benefit is the following, even when upper_limit
> > is a small number:

> > int func(/* ... */)
> > {
> >     /* declarations and statements */

> >     /* comment for the following logical unit */
> >     {
> >         unsigned int sum;    /* comment for sum */

> >         for (i=0; i < upper_limit; i++) {
> >             sum = carry + value1[i] + value2[1];
> >             /* calculation with sum */
> >         }
> >     }

> >     /* ... */
> > }

> This really looks crappy, and I can't see what benefit this
> should bring.

Suppose a long function that's already so cohesive that it's better
not to divide it into two or more smaller functions.

int long_func(/* ... */)
{
    int foo1, foo2;    // objects used through the entire function

    {   // explanation for logical unit #1
        int foo3, foo4;    // object used only in the logical unit #1

        // something to do in this unit
    }

    {   // explanation for logical unit #2
        int foo5, foo6;    // object used only in ...

        // something to do in this unit
    }

    // ...

Quote:
}

I learned this style from very well written programs. Of course, this
can be rewritten simple with mixing declarations with code in C99. Now
can you see the benefit?

[...]

--

Dept. of Physics, Univ. of Seoul



Mon, 04 Apr 2005 22:28:44 GMT  
 repeated allocation and deallocation

Quote:


>> This really looks crappy, and I can't see what benefit this
>> should bring.

> Suppose a long function that's already so cohesive that it's better
> not to divide it into two or more smaller functions.

> int long_func(/* ... */)
> {
>     int foo1, foo2;    // objects used through the entire function

>     {   // explanation for logical unit #1
>         int foo3, foo4;    // object used only in the logical unit #1

>         // something to do in this unit
>     }

>     {   // explanation for logical unit #2
>         int foo5, foo6;    // object used only in ...

>         // something to do in this unit
>     }

>     // ...
> }

> I learned this style from very well written programs. Of course, this
> can be rewritten simple with mixing declarations with code in C99. Now
> can you see the benefit?

Yes, and I'ld use this "feature" of C every time I write a
function to long to make the definition of variables appear close
enough to their use (where close enough is to be defined by the
programmer writing such a function, for me this would be a 50
lines of code, which is about the number of lines my editor can
display at once or with only one page movement). But I don't get
the connection to your original post, where you seemed to be
worried about the performance of allocating and deallocating
variables in a loop-block which you wanted to improve by
introducing a surrounding block where variable definition should
go to.

--

"LISP  is worth learning for  the profound enlightenment  experience
you will have when you finally get it; that experience will make you
a better programmer for the rest of your days."   -- Eric S. Raymond



Mon, 04 Apr 2005 22:56:50 GMT  
 repeated allocation and deallocation

Quote:

[...]

> > Suppose a long function that's already so cohesive that it's better
> > not to divide it into two or more smaller functions.

> > int long_func(/* ... */)
> > {
> >     int foo1, foo2;    // objects used through the entire function

> >     {   // explanation for logical unit #1
> >         int foo3, foo4;    // object used only in the logical unit #1

> >         // something to do in this unit
> >     }

> >     {   // explanation for logical unit #2
> >         int foo5, foo6;    // object used only in ...

> >         // something to do in this unit
> >     }

> >     // ...
> > }

> > I learned this style from very well written programs. Of course, this
> > can be rewritten simple with mixing declarations with code in C99. Now
> > can you see the benefit?

> Yes, and I'ld use this "feature" of C every time I write a
> function to long to make the definition of variables appear close
> enough to their use (where close enough is to be defined by the
> programmer writing such a function, for me this would be a 50
> lines of code, which is about the number of lines my editor can
> display at once or with only one page movement). But I don't get
> the connection to your original post, where you seemed to be
> worried about the performance of allocating and deallocating
> variables in a loop-block which you wanted to improve by
> introducing a surrounding block where variable definition should
> go to.

No, I'm not worring about the performance. If upper_limit is a very
large number, then it can be said that it's related with the
performance issue and then I strongly claim that declarations of auto
objects in a for loop *can* spoil the program. But in this case, I'm
talking about pure style issue, without worring about the performance.

--

Dept. of Physics, Univ. of Seoul



Mon, 04 Apr 2005 23:18:52 GMT  
 repeated allocation and deallocation

Quote:


[...]
>> display at once or with only one page movement). But I don't get
>> the connection to your original post, where you seemed to be
>> worried about the performance of allocating and deallocating
>> variables in a loop-block which you wanted to improve by
>> introducing a surrounding block where variable definition should
>> go to.

> No, I'm not worring about the performance. If upper_limit is a very
> large number, then it can be said that it's related with the
> performance issue and then I strongly claim that declarations of auto
> objects in a for loop *can* spoil the program. But in this case, I'm
> talking about pure style issue, without worring about the performance.

As I said, I find this "feature" useful. Especially if a function
is that long that the use of a variable would be say more than 50
lines from its defintion away. But than my argument against your
claim is, if the implementation chooses to have a less performant
alloc/dealloc-technique for such variables it may have its
reasons. From the languages point of view there is nothing that
can stop a compiler from being less performant with one or the
other way. The very next compiler you'll have to use will
probably do a bad alloc/dealloc-thingy whenevery you introduce a
block.

So what I'm trying to say is, "Don't try to be to tricky". A
decent compiler should probably produce equivalent code for either

{
  unsigned int sum;
  for (i=0; i<upper_limit; i++) {
    sum = carry + value1[i] + value2[1];
  }

Quote:
}

or

for(i=0; i<upper_limit; i++) {
  unsigned int sum = carry + value1[i] + value2[1];

Quote:
}

, shouldn't it? And I wouldn't bother to introduce a workaround for
some brain damaged compiler/implementation in all my code (which
appears to be what you are targeting at as you say this is a
style issue) just because one day a program may not be running
fast enough due to a bad compiler?!!
--

"LISP  is worth learning for  the profound enlightenment  experience
you will have when you finally get it; that experience will make you
a better programmer for the rest of your days."   -- Eric S. Raymond


Mon, 04 Apr 2005 23:44:07 GMT  
 repeated allocation and deallocation

Quote:
>No, I'm not worring about the performance. If upper_limit is a very
>large number, then it can be said that it's related with the
>performance issue and then I strongly claim that declarations of auto
>objects in a for loop *can* spoil the program.

Not really.  If the implementor decided to allocate them on block entry
and deallocate them on block exit, it is because ALL of them can be
allocated or deallocated with one "cheap" machine instruction.

Quote:
>But in this case, I'm
>talking about pure style issue, without worring about the performance.

In most cases, I'd define the variable at function scope, even if I use it
only in one block.  It is more convenient, *to me*, to have all the local
variable definitions gathered together: in one window I look at the
actual code, in another I have all the local definitions displayed and
it is very easy (for me) to move my eyes from one window to the other.
Sometimes, I may use a third window for the file scope declarations.

Dan
--
Dan Pop
DESY Zeuthen, RZ group



Tue, 05 Apr 2005 00:11:18 GMT  
 repeated allocation and deallocation

Quote:



> [...]
> >> display at once or with only one page movement). But I don't get
> >> the connection to your original post, where you seemed to be
> >> worried about the performance of allocating and deallocating
> >> variables in a loop-block which you wanted to improve by
> >> introducing a surrounding block where variable definition should
> >> go to.

> > No, I'm not worring about the performance. If upper_limit is a very
> > large number, then it can be said that it's related with the
> > performance issue and then I strongly claim that declarations of auto
> > objects in a for loop *can* spoil the program. But in this case, I'm
> > talking about pure style issue, without worring about the performance.

> As I said, I find this "feature" useful. Especially if a function
> is that long that the use of a variable would be say more than 50
> lines from its defintion away. But than my argument against your
> claim is, if the implementation chooses to have a less performant
> alloc/dealloc-technique for such variables it may have its
> reasons. From the languages point of view there is nothing that
> can stop a compiler from being less performant with one or the
> other way. The very next compiler you'll have to use will
> probably do a bad alloc/dealloc-thingy whenevery you introduce a
> block.

Again, my concern here is the coding style, not the performance.

Quote:

> So what I'm trying to say is, "Don't try to be to tricky".

Good point.

- Show quoted text -

Quote:
> A
> decent compiler should probably produce equivalent code for either

> {
>   unsigned int sum;
>   for (i=0; i<upper_limit; i++) {
>     sum = carry + value1[i] + value2[1];
>   }
> }

> or

> for(i=0; i<upper_limit; i++) {
>   unsigned int sum = carry + value1[i] + value2[1];
> }

So which is tricky? If the major reason is just to limit the scope
of the object's identifier, the second seems more tricky to me; a code
reader should try to remember the lifetime of the object starts and
end repeatedly until he recognize the fact that the lifetime is not
really important.

Quote:
> , shouldn't it? And I wouldn't bother to introduce a workaround for
> some brain damaged compiler/implementation in all my code (which
> appears to be what you are targeting at as you say this is a
> style issue) just because one day a program may not be running
> fast enough due to a bad compiler?!!

Again, the performance is not my concern in this case.

--

Dept. of Physics, Univ. of Seoul



Tue, 05 Apr 2005 00:38:45 GMT  
 repeated allocation and deallocation

Quote:

writes:

> >No, I'm not worring about the performance. If upper_limit is a very
> >large number, then it can be said that it's related with the
> >performance issue and then I strongly claim that declarations of auto
> >objects in a for loop *can* spoil the program.

> Not really.  If the implementor decided to allocate them on block entry
> and deallocate them on block exit, it is because ALL of them can be
> allocated or deallocated with one "cheap" machine instruction.

Agreed. But, there *can* be an implementation that has to (de)allocate
on every block entry/exit even when it's a little more expensive,
which is the reason I emphasized "can" in my wording; don't ask me the
reason such an implementation has to do, I've never thought it so deep.

Anyway, as I said in other posting in this thread, my real concern is
the style issue.

--

Dept. of Physics, Univ. of Seoul



Tue, 05 Apr 2005 00:51:43 GMT  
 repeated allocation and deallocation

Quote:

> Again, my concern here is the coding style, not the
> performance.

So we're leaving performance behind.

Quote:

>> So what I'm trying to say is, "Don't try to be to tricky".

> Good point.

>> A
>> decent compiler should probably produce equivalent code for either

>> {
>>   unsigned int sum;
>>   for (i=0; i<upper_limit; i++) {
>>     sum = carry + value1[i] + value2[1];
>>   }
>> }

>> or

>> for(i=0; i<upper_limit; i++) {
>>   unsigned int sum = carry + value1[i] + value2[1];
>> }

> So which is tricky? If the major reason is just to limit the scope
> of the object's identifier, the second seems more tricky to me; a code
> reader should try to remember the lifetime of the object starts and
> end repeatedly until he recognize the fact that the lifetime is not
> really important.

This, as you said in your original post is a matter of taste and
for me (as I've got used to example two) example one is more
confusing than the second. I don't have to remeber where the
lifetime starts or ends, as I just appear to know it. For a
reader it should be obvious that lifetime isn't an issue for this
variable as it is merrily introduced in the block (and usually
it is just a helper!).

How about

if(fgets(buffer, sizeof buffer, stdin)) {
  char *endp;

  strtol(buffer, &endp, 0);
  if(endp != '\n') {
    /* this appears to be some bad input */
  }

Quote:
} else {
  /* ... */
}

should this also be rewritten as

{
  char *endp;

  if(fgets(buffer, sizeof buffer, stdin)) {

    strtol(buffer, &endp, 0);
    if(endp != '\n') {
      /* this appears to be some bad input */
    }

  } else {
    /* ... */
  }

Quote:
}

--

"LISP  is worth learning for  the profound enlightenment  experience
you will have when you finally get it; that experience will make you
a better programmer for the rest of your days."   -- Eric S. Raymond


Tue, 05 Apr 2005 01:07:46 GMT  
 repeated allocation and deallocation

Quote:

[...]

> > So which is tricky? If the major reason is just to limit the scope
> > of the object's identifier, the second seems more tricky to me; a code
> > reader should try to remember the lifetime of the object starts and
> > end repeatedly until he recognize the fact that the lifetime is not
> > really important.

> This, as you said in your original post is a matter of taste and

I agree.

Quote:
> for me (as I've got used to example two) example one is more
> confusing than the second. I don't have to remeber where the
> lifetime starts or ends, as I just appear to know it. For a
> reader it should be obvious that lifetime isn't an issue for this
> variable as it is merrily introduced in the block (and usually
> it is just a helper!).

> How about

> if(fgets(buffer, sizeof buffer, stdin)) {
>   char *endp;

>   strtol(buffer, &endp, 0);
>   if(endp != '\n') {
>     /* this appears to be some bad input */
>   }

> } else {
>   /* ... */
> }

> should this also be rewritten as

> {
>   char *endp;

>   if(fgets(buffer, sizeof buffer, stdin)) {

>     strtol(buffer, &endp, 0);
>     if(endp != '\n') {
>       /* this appears to be some bad input */
>     }

>   } else {
>     /* ... */
>   }

> }

You missed a point with this example. In my original code, the *loop*
contains the declaration. In yours, the lifetime doesn't start and end
repeatedly, does it?

--

Dept. of Physics, Univ. of Seoul



Tue, 05 Apr 2005 01:17:54 GMT  
 repeated allocation and deallocation

Quote:

> Even if most actual implementations allocate all objects defined in a
> given function at the entry of the function, on the abstract machine
> (and some implementations) sum is allocated and deallocated repeatedly
> when the for loop is executed.

> Someone can claim that a benefit from the above style is the scope of
> sum is limited to a logical unit related to the object. IMO, a better
> style to get the same benefit is the following, even when upper_limit
> is a small number:

This is not a style, this is hand-optimizing code with particular
actual semantics in mind. As a rule, you don't bother optimizing,
unless it's in a hotspot of the code. Then your first tool is to get
the best possible compiler that your circumstances will allow you to
use (circumstances constraining your compiler choice being platform
considerations, support for necessary language extensions, budget,
etc). There is no point in human-optimizing if you haven't yet applied
the machine optimizer to your hotspot. Only then if it's still not
fast enough, you determine what the actual semantics are and how you
can influence them by manipulating the source program; lastly, you may
have to drop down to assembly language. (Should inline assembly
language coding be considered ``style'' also?)


Tue, 05 Apr 2005 05:54:56 GMT  
 repeated allocation and deallocation


Quote:

> > Even if most actual implementations allocate all objects defined in a
> > given function at the entry of the function, on the abstract machine
> > (and some implementations) sum is allocated and deallocated repeatedly
> > when the for loop is executed.

> > Someone can claim that a benefit from the above style is the scope of
> > sum is limited to a logical unit related to the object. IMO, a better
> > style to get the same benefit is the following, even when upper_limit
> > is a small number:

> This is not a style, this is hand-optimizing code with particular
> actual semantics in mind.

Nope. Even if I writed my first writing as it's related to the
performance issue, it's not my real concern. The assumption that
upper_limit is a small number means that the performance is not
significant anyway. Have you read other postings in this thread?

Quote:
> As a rule, you don't bother optimizing,
> unless it's in a hotspot of the code. Then your first tool is to get
> the best possible compiler that your circumstances will allow you to
> use (circumstances constraining your compiler choice being platform
> considerations, support for necessary language extensions, budget,
> etc). There is no point in human-optimizing if you haven't yet applied
> the machine optimizer to your hotspot. Only then if it's still not
> fast enough, you determine what the actual semantics are and how you
> can influence them by manipulating the source program; lastly, you may
> have to drop down to assembly language. (Should inline assembly
> language coding be considered ``style'' also?)

I fully agree.

Thanks.

--

Dept. of Physics, Univ. of Seoul



Tue, 05 Apr 2005 11:06:10 GMT  
 repeated allocation and deallocation

Quote:



> [...]

>> > So which is tricky? If the major reason is just to limit the scope
>> > of the object's identifier, the second seems more tricky to me; a code
>> > reader should try to remember the lifetime of the object starts and
>> > end repeatedly until he recognize the fact that the lifetime is not
>> > really important.

>> This, as you said in your original post is a matter of taste and

> I agree.

>> for me (as I've got used to example two) example one is more
>> confusing than the second. I don't have to remeber where the
>> lifetime starts or ends, as I just appear to know it. For a
>> reader it should be obvious that lifetime isn't an issue for this
>> variable as it is merrily introduced in the block (and usually
>> it is just a helper!).

>> How about

>> if(fgets(buffer, sizeof buffer, stdin)) {
>>   char *endp;

>>   strtol(buffer, &endp, 0);
>>   if(endp != '\n') {
>>     /* this appears to be some bad input */
>>   }

>> } else {
>>   /* ... */
>> }

>> should this also be rewritten as

>> {
>>   char *endp;

>>   if(fgets(buffer, sizeof buffer, stdin)) {

>>     strtol(buffer, &endp, 0);
>>     if(endp != '\n') {
>>       /* this appears to be some bad input */
>>     }

>>   } else {
>>     /* ... */
>>   }

>> }

> You missed a point with this example. In my original code, the *loop*
> contains the declaration. In yours, the lifetime doesn't start and end
> repeatedly, does it?

I didn't miss it, it was just meant as an clarification for me.
I asked myself whether your approach would ask for extra-blocks
in all circumstances where a variable is introduced inside a
block or if one had to distinguish loops from selections.

Anyhow, even if you say that performance isn't the issue, I can
only see the benefit that a brain damaged implementation wouldn't
continuously alloc/dealloc the introduced variable, and that
doesn't appear to be enough to make me write such quirky little
things.
--

"LISP  is worth learning for  the profound enlightenment  experience
you will have when you finally get it; that experience will make you
a better programmer for the rest of your days."   -- Eric S. Raymond



Tue, 05 Apr 2005 16:13:17 GMT  
 repeated allocation and deallocation

Quote:




> > [...]

> >> > So which is tricky? If the major reason is just to limit the scope
> >> > of the object's identifier, the second seems more tricky to me; a
code
> >> > reader should try to remember the lifetime of the object starts and
> >> > end repeatedly until he recognize the fact that the lifetime is not
> >> > really important.

> >> This, as you said in your original post is a matter of taste and

> > I agree.

> >> for me (as I've got used to example two) example one is more
> >> confusing than the second. I don't have to remeber where the
> >> lifetime starts or ends, as I just appear to know it. For a
> >> reader it should be obvious that lifetime isn't an issue for this
> >> variable as it is merrily introduced in the block (and usually
> >> it is just a helper!).

> >> How about

> >> if(fgets(buffer, sizeof buffer, stdin)) {
> >>   char *endp;

> >>   strtol(buffer, &endp, 0);
> >>   if(endp != '\n') {
> >>     /* this appears to be some bad input */
> >>   }

> >> } else {
> >>   /* ... */
> >> }

> >> should this also be rewritten as

> >> {
> >>   char *endp;

> >>   if(fgets(buffer, sizeof buffer, stdin)) {

> >>     strtol(buffer, &endp, 0);
> >>     if(endp != '\n') {
> >>       /* this appears to be some bad input */
> >>     }

> >>   } else {
> >>     /* ... */
> >>   }

> >> }

> > You missed a point with this example. In my original code, the *loop*
> > contains the declaration. In yours, the lifetime doesn't start and end
> > repeatedly, does it?

> I didn't miss it, it was just meant as an clarification for me.
> I asked myself whether your approach would ask for extra-blocks
> in all circumstances where a variable is introduced inside a
> block or if one had to distinguish loops from selections.

I expect you conclude that the answer is the latter.

Quote:

> Anyhow, even if you say that performance isn't the issue, I can
> only see the benefit that a brain damaged implementation wouldn't
> continuously alloc/dealloc the introduced variable, and that
> doesn't appear to be enough to make me write such quirky little
> things.

I begin to agree with you and other people who claim that it's enough
useful as the discussion progresses. But the feature introducing an
extra block structure to divide a function to several logical unit is
still useful, when C99's features are not available.

--

Dept. of Physics, Univ. of Seoul



Tue, 05 Apr 2005 16:30:13 GMT  
 
 [ 22 post ]  Go to page: [1] [2]

 Relevant Pages 

1. Allocation and deallocation of exceptions...

2. allocation/deallocation warnings in splint

3. Question regarding memory allocation/deallocation

4. memory allocation/deallocation for tree (a prelimary summary)

5. Strange memory allocation and deallocation errors:

6. Memory Allocation and DeAllocation (new and free) !?

7. CObjArray allocation/deallocation

8. Heap Allocation/Deallocation in a DLL

9. DLL Memory Allocation and Deallocation

10. Memory allocation/deallocation for tree? Any good way?

11. Tree memory allocation, pool memory allocation

12. Array Deallocation

 

 
Powered by phpBB® Forum Software