need argument for try catch blocks

K

Keith H Duggar

Again, I am not equating C-style to lousy.

I think most readers would find that you have both explicitly
and implicitly done so multiple times in this thread. Perhaps
you did not /intend/ to do so; if so, fine we can chalk it up
to poor communication or temporary irrationality caused by
your emotional frustration with work.
I am equating the mixing of C-Style into OO C++

You have admitted that you never learned proper C programming
and never worked professionally as a C programmer. Given that,
it is virtually certain that you have absolutely no clue as to
what "C-Style" is. You just have your own personally invented
concept serving as a vent for your frustration with crap /C++/
code and a certain peer you disagree with.
as the source of months of debugging, and therefore lousy. 9
times out of 10 the person doing this doesn't even have a basic
understanding of the C++ language, but they are some senior
person whom has programmed C all their life.

Obviously you are extremely frustrated driving you to disparage
your colleague and rant against your "C-Style" phantom. Instead,
why don't you just rant about "crap code" (which everyone would
get behind) and leave your colleague and C out of it?


Yes you are. You think object == OOP; it doesn't.
I am not confused with programming paradigms.
[snip]

In order to even have constructors and deconstructors we are implying
we are making objects in the first place! Please tell me how you can
have RAII without OOP. Generic Programming doesn't explictly imply
objects at all.

Yes, you are confused with paradigms. Using abstract data types
is not OOP. Deterministic automatic constructors+destructors is
not OOP. In other words RAII != OOP.

RAII is a paradigm quite unique to C++ and orthogonal to OOP.
Indeed, most if not all OO programming languages do not even
support RAII.
Regardless, C-style programming implies neither of these.

And "C-style" has nothing to do with your problems. Your problems
are with "crap C++ code" and frustration.
You are both also talking as if I am introducing the exceptions. Nay!
I am trying to handle them! Someone else was responsible for throwing
exceptions left and right from c-style code that had a disregard for
freeing of resources.

No, that is simply crap /C++/ code and entirely understandable
frustration with it.

KHD
 
A

Alf P. Steinbach /Usenet

* Christopher, on 03.06.2011 16:51:
At the day
of my hire, I was handed the source code for a windows service that
will not even start up 9 times out of 10, because of one unhandled
exception or another. 3 months of handling them one by one and they
continue to appear. When it does start up, it runs for all of an hour
or two before crashing.

Ditch that code.


Cheers & hth.,

- Alf
 
C

Christopher

You have admitted that you never learned proper C programming
and never worked professionally as a C programmer. Given that,
it is virtually certain that you have absolutely no clue as to
what "C-Style" is.

One does not have to work professionally as a C programmer to quickly
identify C code. When one reads sprintf, printf, memcpy, malloc,
strcpy, atoi, itoa, and a host of other C functions that have C++
replacements, one can quickly make the assumption "A C Programmer was
here!"

When one spends more than 75% of their 10 year career debugging files
where one has found that "A C programmer was here!" and finding errors
related to their source code and their lack of knowledge on language
features specific to C++, one can say something along the lines of
"There is always that one guy writing C-Style code..." to which you
took great offense.
You just have your own personally invented
concept serving as a vent for your frustration with crap /C++/
code and a certain peer you disagree with.

I haven't invented an experience. An experience has formed a concept.
It isn't crap C++. In most cases it was well formed, working C++,
until it was sprinkled with C.
Obviously you are extremely frustrated driving you to disparage
your colleague and rant against your "C-Style" phantom. Instead,
why don't you just rant about "crap code" (which everyone would
get behind) and leave your colleague and C out of it?

Frustration? Correct. It's part of the job though and always is. My
rant is not againt one colleague. There have been enough of these
stereotypical programmers to fill a building during my career.

Yes you are. You think object == OOP; it doesn't.

Nope. I think OOP implies objects. OOP implies a whole lot more than
that as well.

Yes, you are confused with paradigms. Using abstract data types
is not OOP. Deterministic automatic constructors+destructors is
not OOP. In other words RAII != OOP.

I never used an equal or not equal sign. I am saying RAII REQUIRES
OOP. "REQUIRES" is not the same as "EQUALS". Please give an example of
RAII without using any OOP concepts and let's critique the code
together.

RAII is a paradigm quite unique to C++ and orthogonal to OOP.
Indeed, most if not all OO programming languages do not even
support RAII.

What does that have to do with anything?
And "C-style" has nothing to do with your problems. Your problems
are with "crap C++ code" and frustration.

As stated previously, one can quickly identify C code. When one
identifies C code, one can make the assumption a C programmer has
worked on the source file. When the source file is the location of the
majority of issues, one can make the assumption that a C programmer
has crapped on the code. When this happens over and over throughout
the course of a 10 year career, One can make the statements that I've
made.

I'll say again, you are making this into some campaign for C code.
Your campaign doesn't fit here. THE ISSUE IS WITH PEOPLE WHO WRITE C
CODE WITHOUT AN UNDERSTANDING OF C++. There is nothing for you to
campaign against in that statement.

....Actually the issue was with "Where should we catch exceptions?"
You made a whole new issue from there.
 
E

Edek

RAII is a paradigm quite unique to C++ and orthogonal to OOP.
Indeed, most if not all OO programming languages do not even
support RAII.

OT: What about the with-construct in Python?

with file.open(...) as f:
....
.... any block leave calls f's cleanup func, closing file
....

Looks like RAII to me.
And "C-style" has nothing to do with your problems. Your problems
are with "crap C++ code" and frustration.


No, that is simply crap /C++/ code and entirely understandable
frustration with it.

I kind of don't really understand why this frustration leads very often
to being a Best Practises Prophet coupled with blaming everyone around.
Isn't the situation just working with legacy software,
not even crappy one, just the windowz API is such, and other
parts of it remember the old times, and newer parts are written in a
different way and so on, and maybe the "C-Style" colleague is really
just aware of the fact that the software does not rewrite itself?
(don't say this is off-topic - just a different aspect)
Instead,
why don't you just rant about "crap code" (which everyone would
get behind) and leave your colleague and C out of it?

Because that would be more difficult thing to do? :) Having some
notion of OOP/OOA/RAII/whatever makes one feel soo much better. Calling
code 'crappy' helps too (maybe it is crappy, how can I know).

I also heard macros are really really evil, take MAX(a++), who has not
heard about this one? Never use macros ;-)
 
S

Stefan Ram

Edek said:
OT: What about the with-construct in Python?
with file.open(...) as f:
Looks like RAII to me.

This »with« was used in Common Lisp much earlier. I would
not call it »RAII«.

Here is one attempt to implement something like that in C:

#include <stdio.h>
#include <stdlib.h>
#include "mylib.h" /* to be shown below */

/* print a file (copy it to stdout) */

double print( FILE * const file )
{ return copy( stdout, file ); /* file will be closed here */ }

int main( void )
{ int result = EXIT_FAILURE;
if( open( "source.txt", "r", print ))
fprintf( stderr, "unable to open source file.\n" );
else result = EXIT_SUCCESS;
return result; }

The file will be closed when returning from »print«.

The two functions »open« and »copy« are assumed to be
defined in the library consisting of mylib.h and mylib.c,
where mylib.c might look like:

#include <stdio.h>
#include <stdlib.h>

double open
( const char * const path,
const char * const mode,
double( *continuation )( FILE * ) )
{ FILE * const file = fopen( path, mode ); double result = 0;
if( !file )result = 1./1024; else
{ result += continuation( file );
if( fclose( file ))result += 2./1024; }
return result; }

double copy
( FILE * const target,
FILE * const source )
{ int result = -1;
for( int looping = 1; looping; )
{ int const c = fgetc( source );
if( feof( source ))looping = 0, result = 0;
if( ferror( source ))looping = 0, result = 1;
if( c != EOF )putc( c, target ); }
return result; }

Ok, the double return code is somewhat ugly, but this is
just a draft to convey the idea. Also, one would pass an
additional data structure with client data through the
callback functions.
 
J

Joshua Maurice

OT: What about the with-construct in Python?

with file.open(...) as f:
     ....
     .... any block leave calls f's cleanup func, closing file
     ....

Looks like RAII to me.

It's a poor man's RAII. It's functionally equivalent to a finally
block, but at least all the relevant code is in one spot as opposed to
spread out with a "try { ... } finally {}". However, the problem with
both is that ownership is not always restricted to a particular stack
scope.

I'd rather not get into a definitional war over RAII, but this highly
related concept which I'm about to explain, if not RAII itself, is
relatively unique to C++ as far as I know. It is very related to the
concept of ownership. The C++ way, either RAII or very related to
RAII, is to code in such a way that all objects always have an owner,
a clear and identifiable condition that will release that resource
when it's no longer needed. This ownership relationship forms an
ownership graph, which when properly done is acyclic. It usually has
(most of) its roots (or leaves if you prefer it that way) in objects
on the stack. The beauty and utility of this approach is that you no
longer have to worry about almost all resource collection on error
paths, including thrown exception code flow paths. The implicit
calling of functions on stack exit, which in turn cause the implicit
calling of other functions, and so on, allow us to quite neatly clean
up resources.

If you code to this idiom, it becomes exceptionally difficult to
accidentally "leak" something, /and much more importantly/ if you do
detect a leak, it becomes much easier to reason about where the bug
is. Find out where that object lost being owned and fix it. It allows
you to much more easily reason about code correctness in isolation
from other code.

This implicit calling of functions on stack exit, and for sub-objects,
is relatively unique to C++ as far as I know.

Is it syntactic sugar? In one sense, insofaras all higher level
concepts are to some degree syntactic sugar over assembly. Does its
use lead to a far better quality code than without, given the same
"man hours"? I would argue yes.
 
Ö

Öö Tiib

Just to clear the possibility: the team I'm with doesn't need one.

I'm rather considering this as a 'make money' option in some distant
future (read: probably never)

Yes, likely never since there are always better opportunities of
making some money. Devs buy them rarely if not integrated into IDE
(and IDE is also often downloaded and not bought). Some manager may
buy something but manager has to buy from Rational or Intel or
MicroSoft or Apple or Oracle or IBM (not you). Otherwise competing
manager can accuse him of buying crappy and unreliable tools from Edek
as reason that causes the projects to fail.
...

The first thing I thought of when thinking about how to write such tools
is that C++ is indeed complex to parse, let alone transform.
I don't agree with the defective argument: most simple refactoring
mechanisms built into IDEs fall back to 'Preview' allowing human
intervention, either when the tool is not sure or just for the sake
of checking.

Yes, i did try to soften "defective". The simple things you describe
are usually self-critical enough. That does not mean they are
sufficiently flexible (configurable) or context-aware. On lot of cases
the resulting code does not compile. Even if it does compile it is
highly likely that you have to further edit it (for example move
#include or member function declaration added by tool to correct
place).
Actually, I always consider refactoring more an obstruction to doing
unit tests (or the other way round...);
I do agree that having unit tests vastly helps when doing ANY
changes.

I don't understand the obstruction i see only pure aid. Unit test
helps refactorer to see if he broke a contract of a class or a
function. If he broke then that means on worst case few hours of his
to repair the things. If there are no unit tests it may mean
cooperatively several man months of work time plus frustrated
customers thanks to his "refactoring".
 
K

Keith H Duggar

OT: What about the with-construct in Python?

with file.open(...) as f:
† † †....
† † †.... any block leave calls f's cleanup func,closing file
† † †....

Looks like RAII to me.

It is a very limited/restricted form of RAII, yes. For example,
this form of RAII is not usable when the resource is accessed by
more than one function. Unfortunately the __del__ methods do not
reliably provide more general RAII either (as one discovers soon
after running their Python program on Jython).

Anyhow, it's always interesting (and I imagine highly satisfying
for some) to watch such languages evolve /towards/ C++. The more
vociferously anti-C++ the language's users are, the more ironic
and amusing is the evolution.
I kind of don't really understand why this frustration leads very often
to being a Best Practises Prophet coupled with blaming everyone around.

Indeed Christopher's reaction to his work is very common. In my
opinion it stems from a basic frustration at seeing code making
/known/ and in principle /preventable/ mistakes.

Furthermore, not only are these preventable mistakes costing the
company time and money, but, you as the maintainer are forced to
dive head first into the warped and twisted tangle of crap code.
You are forced to comprehend it, to read it again and again, to
discover its darkest hidden corners, to run it, to test it, and
Llort forbid /reproduce/ it's quirks in new code!

In short, you are forced to wallow in and drink from a cesspool
that in your mind should never have been created.
Isn't the situation just working with legacy software, not even
crappy one, just the windowz API is such, and other parts of it
remember the old times, and newer parts are written in a different
way and so on, and maybe the "C-Style" colleague is really just
aware of the fact that the software does not rewrite itself?
(don't say this is off-topic - just a different aspect)

Precisely! That perspective is the key to rising above the gut
emotional reaction and regaining control. The key realization
is that all of us are performing with /finite/ resources (time,
talent, discipline, health, money, etc) impinged by reality. (1)
Because that would be more difficult thing to do? :) Having some
notion of OOP/OOA/RAII/whatever makes one feel soo much better. Calling
code 'crappy' helps too (maybe it is crappy, how can I know).

Indeed people always want to feel better about themselves and it
seems bashing others is a natural way to achieve this. I'm trying
to help Christopher /realize/ that he is doing this so that he
can rise above his current emotional limitations and mature as a
professional.
I also heard macros are really really evil, take MAX(a++),
who has not heard about this one? Never use macros ;-)

Yes MAX is an example where C++ would /not/ use a macro given
that C++ offers superior solutions for that case. However, at
this time macros remain an /at times necessary/ evil in C++.

KHD

(1) as an example of finite self-control and mental health, Leigh
Johnston is physiologically incapable of choosing not to respond
to trolls directed at him. See the thread rooted here:

http://groups.google.com/group/comp.lang.c++/msg/c007296f3c169cca
 
B

Balog Pal

Christopher said:
I never used an equal or not equal sign. I am saying RAII REQUIRES
OOP. "REQUIRES" is not the same as "EQUALS".

And why is OOP required for RAII? It clearly is not. Unless you mean just
the few dozen classes used as the resource controllers themselves.

Normally OOP is used as a style imposed on the majority of a project (hence
the second O).

With C++ you're welcome to just use a few classes and write the rest in
whatever orientation or mix thereof. Including use mostly free functions
around. But keep to full RAII in the implementation and the state.
 
E

Edek

Edek said:
OT: What about the with-construct in Python?
with file.open(...) as f:
Looks like RAII to me.

This »with« was used in Common Lisp much earlier. I would
not call it »RAII«.

Here is one attempt to implement something like that in C:

Code:
Ok, the double return code is somewhat ugly, but this is
just a draft to convey the idea. Also, one would pass an
additional data structure with client data through the
callback functions.
[/QUOTE]

Powers of two are really wicked in this case; I think they don't add up,
in this draft, but that was not the point. I don't program in C much,
but as far I know one can write a lot of things which are really
object oriented in plain C, using such twisted concepts, macros for
example, to get any data structures and flowas. The concepts one gets
are more important that the uglyness of implementation - usage counts.

Edek
 
E

Edek

If you code to this idiom, it becomes exceptionally difficult to
accidentally "leak" something, /and much more importantly/ if you do
detect a leak, it becomes much easier to reason about where the bug
is. Find out where that object lost being owned and fix it. It allows
you to much more easily reason about code correctness in isolation
from other code.

This implicit calling of functions on stack exit, and for sub-objects,
is relatively unique to C++ as far as I know.

I do agree with almost everything you wrote, expect one thing:
reasoning about it is certainly easy, when things are consistent
and the people involved are on the same page.
This ownership relationship forms an
ownership graph, which when properly done is acyclic.

If one could find a solution that would allow cycles without GC...
That's probably the only thing I don't
like about sharing resources or building arbitrary structures. One can
argue this is not that bad in most cases, when this can be handled by
weak references, by avoiding cycles, or by cleaning up (candidate for
RAII style itself).
 
K

Keith H Duggar

And why is OOP required for RAII? It clearly is not. Unless you mean just
the few dozen classes used as the resource controllers themselves.

It is the usual kind of definitional game that he wants to play.
Ie to Christopher any coding /using/ objects is by (his personal)
definition object /oriented/. Of course not only does that match
any common definition of OOP (as far as I see) but it even ignores
the common sense meaning of the word /oriented/. For example, I'm
certain that to you and I (and probably most people) this code:

...
auto_ptr<T> hold(new T)
...

is /not/ automatically object /oriented/. But Christopher will
say "Yes it is! It uses objects which are a concept owned by OOP!
And the object even has a destructor. ZOMG it's obviously OOP!"

To me that's as stupid as saying any code having functions is
"functional programming" or any code that uses double is "double
oriented programming". Different programming paradigms share some
basic tools but use the tools in a different way with a different
focus. It is that usage pattern and focus that distinguishes them.

In my view RAII/RRID is sui generis, an idiom orthogonal to OOP
and quite unique to C++, built upon a basic mechanism also unique
to C++: automatic deterministic paired constructor + destructor.

KHD
 
J

Joshua Maurice

I do agree with almost everything you wrote, expect one thing:
reasoning about it is certainly easy, when things are consistent
and the people involved are on the same page.

Agreed. Perhaps I was a bit too strong. It's no silver bullet. It
requires a fair share of active concern from the programmer at all
times, unlike the standard "allocate and forget" of GC. It's very
useful when used correctly, and does little to help if used
incorrectly or not at all.
 
D

Dombo

Op 03-Jun-11 16:51, Christopher schreef:
At the day of my hire, I was handed the source code for a windows service that
will not even start up 9 times out of 10, because of one unhandled
exception or another.

If that is your problem, why don't you install a structured exception
handler (SEH - Windows feature not standard C++) and dump the stack when
the handler is called? That way you know exactly which exception was
thrown from where and fix the problem at the source rather than
polluting the code with unnecessary catch blocks to hide the problem.
 
M

MikeP

Keith said:
That's a good analogy.

But inappropriately applied in this instance.
Life Would Suck (TM) if passports were
checked on every corner. And code that checks every statement
/individually/ for exceptions Sucks For Sure.

Orthogonal issue.
 
M

MikeP

Stefan said:
This is exacly what exceptions were invented to prevent.

No. Exceptions cannot PREVENT that coding style, so therefore, exceptions
were not invented to PREVENT that (or else they would have been shelved
as a miserable failure against that requirement).

The solution the OP is looking for is how to create exception-safe code.
He should be worried about his code and not the other code. His code
needs to be robust in the case of exception from the other code and he
needs to be aware of the exceptions the other code throws (what something
can throw is part of knowing how to use the library). Wrapping calls in
try blocks is decidedly not the C++ idiomatic way of doing that (not that
catching to clean up, rather than handle, must absolutely never be used
though).
 
M

MikeP

Balog said:
Hell no. Resources must be handler by RAII, and never left to hang
around "raw". And mandatory release code must not be multiplicated at
every possible exit.

While RAII is the suggested C++ style, using exceptions to facilitate
clean up is not prohibited. RAII is not the only way that clean-up can be
done. Your use of 'must' is incorrect. 'should' would have been a better
word to use.
 
M

MikeP

Balog said:
Bad Thing (TM).

Error codes are for communication with the immediate caller.
Exceptions are for communication long distance. Several callers
upward typically. It is like checking passports on every corner
instead of doing that only at the country borders.

Exceptions are for handling errors. ALL of them. You
don't gain the advantage of exceptions if you only sprinkle them around
here and there and then do the same with return error codes, for then you
still have the proverbial weak link in the chain (unchecked return
codes/unnoticed errors). An application program is only as robust as its
"weakest link". There should not be a thought process that goes something
like, "depending on WHERE in the call chain this error is expected to be
handled, I'll either apply PORCs (Plain Old Return Codes) or exceptions".
When robustness counts, use exceptions. Always and everywhere and never
use PORCs.
 
Ö

Öö Tiib

Exceptions are for handling errors. ALL of them. You
don't gain the advantage of exceptions if you only sprinkle them around
here and there and then do the same with return error codes, for then you
still have the proverbial weak link in the chain (unchecked return
codes/unnoticed errors). An application program is only as robust as its
"weakest link". There should not be a thought process that goes something
like, "depending on WHERE in the call chain this error is expected to be
handled, I'll either apply PORCs (Plain Old Return Codes) or exceptions".
When robustness counts, use exceptions. Always and everywhere and never
use PORCs.

That sounds like the usual "silver bullet" and "trigger happy"
misconception of *ALWAYS* and *NEVER*. Have you written some software
or are you just trolling?

First, the errors that happen often, (for example a noise from some
communication device) should be handled without exceptions from
performance point of view.

Second, things that are unclear if they are errors should be always
handled without exceptions. Why std::set<>::insert() returns
pair<bool,iterator> (same with std::map)? Because on lot of cases it
is only known to caller if inserting to set or to map something that
was already there is error or not.

Third, when the function should clean, erase, release or close
something but fails. These functions may be are called from
destructors and the little problems and failures of a janitor do not
matter on lot of cases. Therefore these should work without throwing
exceptions. Throwing from such is invasive, bad design and the true
weakest link from robustness point of view.

These were only first few cases that popped into mind, but they feel
lot enough to show your ideology of "ALL errors" as quite
questionable.
 
S

Stefan Ram

Öö Tiib said:
First, the errors that happen often, (for example a noise from some
communication device) should be handled without exceptions from
performance point of view.

What is an error?

What is noise? (in the above context)

What makes that noise be an error?
things that are unclear if they are errors (...)

»things of which it is not known whether they are errors (...)«?
 

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,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top