Topic: Creeping feature #769: `new auto


Author: shap@hal.com (Jonathan Shapiro)
Date: 9 Jul 91 01:11:42 GMT
Raw View
In article <14847@exodus.Eng.Sun.COM> chased@rbbb.Eng.Sun.COM (David Chase) writes:
>In article <1991May27.233808.14632@hal.com> shap@hal.com (Jonathan Shapiro) writes:
>>In article <12759@exodus.Eng.Sun.COM> chased@rbbb.Eng.Sun.COM (David Chase) writes:
>>>In theory, there's no need for alloca.  All the machinery needed to
>>>implement running-of-destructors-for-local-objects can be used to
>            ****************************************
>>>simulate alloca on top of malloc and free.  It's not as efficient, but
>>>it isn't impossible.
>>>
>>>David Chase
>>>Sun
>...
>>Until recently, I was inclined to agree with you. Since then, I have
>>run into at least one case where the need to use malloc/free becomes
>>impossibly cumbersome: functions that do error recovery or error-based
>>abandonment.
>
>Nope, I included that in behavior in my model.  Once you also
>implement the machinery for exception handling in C++...

>Again, I don't recommend this implementation -- my point is definitely
>"in theory".  (What was this all about, anyway?  Someone wanted a
>nifty keyword on "new" to get simulated alloca?  That's moderately
>reasonable, but not necessary.)
>
>David Chase
>Sun

Yes, alloca could be simulated that way.  No, it's not a good way to
do it.  The point of alloca is to guarantee that the pointers get
properly deallocated on function bailout.  I concur that this can be
accomplished with the exceptions mechanism given proper scoping, but I
submit that this complicates the code quite a lot, and exception
handling code is convoluted enough...




Author: shap@hal.com (Jonathan Shapiro)
Date: 9 Jul 91 01:13:41 GMT
Raw View
In article <72915@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>In article <1991May27.233808.14632@hal.com> shap@hal.com (Jonathan Shapiro) writes:
>>Until recently, I was inclined to agree with you. Since then, I have
>>run into at least one case where the need to use malloc/free becomes
>>impossibly cumbersome: functions that do error recovery or error-based
>>abandonment.
>>
>>Consider a function that does the following:...
>
>I disagree.  Its easy to solve the kinds of problems that alloca can
>solve from within C++ -- see the following simple-minded example.
>Alloca simply allows one to create variable sized objects of known
>lifetime [namely the lifetime of the surrounding routine] and this
>is not a hard problem anyway.

If you believe this, you have never written production quality code
that does proper error handling.

It's a hard problem, deserving of thought.




Author: mat@mole-end.UUCP (Mark A Terribile)
Date: 13 Jul 91 22:11:53 GMT
Raw View
... shap@hal.com (Jonathan Shapiro) writes:
> ... chased@rbbb.Eng.Sun.COM (David Chase) writes:
> >... shap@hal.com (Jonathan Shapiro) writes:
> >>... chased@rbbb.Eng.Sun.COM (David Chase) writes:

> >>> ... there's no need for alloca.  All the machinery needed to implement
> >>>running-of-destructors-for-local-objects can ... simulate alloca ...

> >>... I have run into at least one case where ... to use malloc/free becomes
> >>impossibly cumbersome: functions that do error recovery or ... abandonment.

> >...  Once you also implement the machinery for exception handling in C++...

> Yes, alloca could be simulated that way.  No, it's not a good way to
> do it.  ... this can be accomplished with the exceptions mechanism given
> proper scoping, but I submit that this complicates the code quite a lot,
> and exception handling code is convoluted enough...

If we are talking about a C++ with exception handling, then we are talking
about a C++ with templates, no?  It seems to me that one of the first
things in a template library ought to be

 template < class T >
 class Temp_obj
 {
   public:
  Temp_obj( T* atp )
    : Ts_ptr( atp )
  { };

  ~Temp_obj()
  { delete Ts_ptr; };

  operator T*() const { return Ts_p; };

  T* operator->() const { return Ts_p; };
  T* operator->*() const { return Ts_p; };

   private:
  T* Ts_ptr;
 };

Doesn't this do just what is necessary?

 Temp_obj<String> t_msg = new String( arg_str );

Undoubtedly there are issues that get more interesting, and probably
better ways to write the class, but I would think that this is the
right way to do it.

Inheritance represents building data/entity upon data/entity.  Templates
represents the building of algorithm/relationship upon algorithm/relationship.
--

 (This man's opinions are his own.)
 From mole-end    Mark Terribile




Author: jimad@microsoft.UUCP (Jim ADCOCK)
Date: 13 Jul 91 01:23:01 GMT
Raw View
In article <1991Jul9.011341.23524@hal.com> shap@hal.com (Jonathan Shapiro) writes:
|>Alloca simply allows one to create variable sized objects of known
|>lifetime [namely the lifetime of the surrounding routine] and this
|>is not a hard problem anyway.
|
|If you believe this, you have never written production quality code
|that does proper error handling.
|
|It's a hard problem, deserving of thought.

Presumably why some prople thought it through and decided to add
exceptions with proper stack unwinding.




Author: gyro@kestrel.edu (Scott Layson Burson)
Date: 2 May 91 07:49:28 GMT
Raw View
It struck me today that it would be awfully nice to have a high level,
type-safe interface to `alloca' (which allocates a block of memory of
specified size in the caller's stack frame).

A syntax is easily enough come by: `new auto <type>'.

This probably won't fly, since `alloca' is not in the ANSI library and
may be difficult to write for some implementations (though I can't
think why offhand), and so it will probably be considered something
that shouldn't be required in a C++ implementation.

Besides, any particular implementation can provide this functionality,
by overloading `::operator new'.  (On the other hand, different
implementors may choose different "placement" argument types to
specify stack allocation, and it would be nice if this were at least
semi-standard.)

Anyhow, caveats notwithstanding, having thought of this I couldn't
resist mentioning it.

-- Scott
Gyro@Reasoning.COM




Author: chased@rbbb.Eng.Sun.COM (David Chase)
Date: 2 May 91 22:47:43 GMT
Raw View
gyro@kestrel.edu (Scott Layson Burson) writes:
>It struck me today that it would be awfully nice to have a high level,
>type-safe interface to `alloca' (which allocates a block of memory of
>specified size in the caller's stack frame).

>A syntax is easily enough come by: `new auto <type>'.

>This probably won't fly, since `alloca' is not in the ANSI library and
>may be difficult to write for some implementations ...

In theory, there's no need for alloca.  All the machinery needed to
implement running-of-destructors-for-local-objects can be used to
simulate alloca on top of malloc and free.  It's not as efficient, but
it isn't impossible.  Compilers for systems w/o alloca will just need
to work a little harder.

Sigh.  Another feature.  Has anyone considered removing features from
the language instead of adding them?

David Chase
Sun




Author: shap@hal.com (Jonathan Shapiro)
Date: 27 May 91 23:38:08 GMT
Raw View
In article <12759@exodus.Eng.Sun.COM> chased@rbbb.Eng.Sun.COM (David Chase) writes:
>In theory, there's no need for alloca.  All the machinery needed to
>implement running-of-destructors-for-local-objects can be used to
>simulate alloca on top of malloc and free.  It's not as efficient, but
>it isn't impossible.
>
>David Chase
>Sun

David:

At one level I agree completely.  In essence your argument says that
there cannot exist a compiler that can handle C and cannot handle
alloca.

Until recently, I was inclined to agree with you. Since then, I have
run into at least one case where the need to use malloc/free becomes
impossibly cumbersome: functions that do error recovery or error-based
abandonment.

Consider a function that does the following:

 allocate something

 conditionally return failure

 allocate something else

 conditionally return failure

 allocate something else

 deallocate everything
 return success

In the absence of alloca(), the management of deallocation becomes a
very likely source of programmer error, especially as the function is
maintained by third parties.

In my view, this is a compelling reason to have alloca.

Jonathan Shapiro
shap@hal.com




Author: chased@rbbb.Eng.Sun.COM (David Chase)
Date: 10 Jun 91 20:48:25 GMT
Raw View
In article <1991May27.233808.14632@hal.com> shap@hal.com (Jonathan Shapiro) writes:
>In article <12759@exodus.Eng.Sun.COM> chased@rbbb.Eng.Sun.COM (David Chase) writes:
>>In theory, there's no need for alloca.  All the machinery needed to
>>implement running-of-destructors-for-local-objects can be used to
            ****************************************
>>simulate alloca on top of malloc and free.  It's not as efficient, but
>>it isn't impossible.
>>
>>David Chase
>>Sun
...
>Until recently, I was inclined to agree with you. Since then, I have
>run into at least one case where the need to use malloc/free becomes
>impossibly cumbersome: functions that do error recovery or error-based
>abandonment.

Nope, I included that in behavior in my model.  Once you also
implement the machinery for exception handling in C++ (whatever
machinery that is) you can simulate alloca in all important respects.
It could be horribly expensive if your exception-handling
implementation was bad (i.e., high cost in the normal case), or if
your memory allocator was slow (as it often is), but it would work
correctly.

Again, I don't recommend this implementation -- my point is definitely
"in theory".  (What was this all about, anyway?  Someone wanted a
nifty keyword on "new" to get simulated alloca?  That's moderately
reasonable, but not necessary.)

David Chase
Sun




Author: jimad@microsoft.UUCP (Jim ADCOCK)
Date: 14 Jun 91 19:29:44 GMT
Raw View
In article <1991May27.233808.14632@hal.com> shap@hal.com (Jonathan Shapiro) writes:
>Until recently, I was inclined to agree with you. Since then, I have
>run into at least one case where the need to use malloc/free becomes
>impossibly cumbersome: functions that do error recovery or error-based
>abandonment.
>
>Consider a function that does the following:
>
> allocate something
>
> conditionally return failure
>
> allocate something else
>
> conditionally return failure
>
> allocate something else
>
> deallocate everything
> return success
>
>In the absence of alloca(), the management of deallocation becomes a
>very likely source of programmer error, especially as the function is
>maintained by third parties.
>
>In my view, this is a compelling reason to have alloca.

I disagree.  Its easy to solve the kinds of problems that alloca can
solve from within C++ -- see the following simple-minded example.
Alloca simply allows one to create variable sized objects of known
lifetime [namely the lifetime of the surrounding routine] and this
is not a hard problem anyway.

Rather, the hard problem is managing the deallocation of objects of
indefinite lifetime, which in general is not a solvable problem excepting
the use of garbage collection.  To which I propose:  Garbage Collection.
Given garbage collection, any advantages of alloca go away anyway,
since GC schemes exist where allocation simply becomes an inline ptr
addition -- which is as efficient or better than alloca anyway.

----



extern "C"
{
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
}

void* traced_malloc(size_t size)
{
 void* p = malloc(size);
 printf("allocate %d bytes at $%lX\n", size, (long)p);
 return p;
}

void traced_free(void* p)
{
 printf("free at $%lX\n", (long)p);
}

void* operator new(size_t size) { return malloc(size); }
void operator delete(void* p) { free(p); }

#define malloc(x) traced_malloc(x)
#define free(x) traced_free(x)

int failed() // simulate unpredictable failures
{
 return !(3 & rand());
}

class Tracker
{
public:
 void* p;
 operator void*() { return p; }
 Tracker(void* pT) : p(pT) {}
 Tracker() : p(0) {}
 ~Tracker() { if (p != 0) free(p); }
};

#define FAILURE 1
#define SUCCESS 0

int troublesome_routine()
{
 // allocate something:

 Tracker p1 = malloc(100);

 // conditionally return failure:

 if (failed())
  return FAILURE;

 // allocate something else:

 Tracker p2 = malloc(200);

 // conditionally return failure:

 if (failed())
  return FAILURE;

 // allocate something else:

 Tracker p3 = malloc(300);

 // conditionally return failure:

 if (failed())
  return FAILURE;

 // trackers will automatically deallocate everything, so just:

 return SUCCESS;
}


// lets try these "troublesome" routine a few times and see what happens:

main()
{
 for (int tries=0; tries<10; ++tries)
 {
  printf("----------------------\n");
  troublesome_routine();
 }
}

// ---- its no trouble at all!