Exceptions handling in pure C

B

Borneq

How can translate C++ to C code with exceptions handling? Unfortunately
Stroustrup translator cfron has only source and not compiled, llvm command
to translate C++ => C not works.
 
B

BGB

There isn't any, you have to rewrite the code from scratch.

well, it is possible, either to use OS-specific mechanisms (like Win32
SEH), or write ones' own exception-handling system (potentially
involving linked-lists and longjmp), and rewrite any code to use this.

it is kind-of ugly, but it sort of works...
 
J

James Kuyper

How can translate C++ to C code with exceptions handling? Unfortunately
Stroustrup translator cfron has only source and not compiled, llvm command
to translate C++ => C not works.

C doesn't have exception handling; it's one of the many features that
C++ added to C. You can use setjmp()/longjmp() to implement a similar
functionality, but doing so is much more complicated than having
exceptions as a built-in feature of the language. That's precisely why
Stroustrup put exceptions in C++.

One of the more important complications has to do with destructors,
another C++ feature that doesn't exist in C. In C++, objects with
automatic storage duration and class type have their destructors
automatically called when their lifetime ends, even if it ends as a
result of an exception being thrown. Furthermore, it is guaranteed that
the destructors will be called in the reverse of the order in which the
constructors were called. When you translate your code to C, you'll have
to move the clean-up code from your C++ destructors into ordinary C
functions, and you'll have to insert explicit calls to them, rather than
relying on them being called implicitly. In particular, you need to make
sure that they get called even when you call longjmp() to emulate C++
exception handling. This is going to require that you keep track, in
some manner, of the list of destructors that need to be called; given
that the corresponding setjmp() will often be in a very different
section of the code, keeping track of which destructors need to be
called is non-trivial.

Redesigning your code so it doesn't rely upon exception handling is
painful, but can result in better C code than trying to translate C++
exception handling directly.

On the other hand: if your entire program never actually handles
exceptions, then you may be able to adequately emulate exceptions simply
by replacing throw() with exit(). That's the case for the C++ code I'm
working on right now.
 
B

Borneq

Użytkownik "James Kuyper said:
On the other hand: if your entire program never actually handles
exceptions, then you may be able to adequately emulate exceptions simply
by replacing throw() with exit(). That's the case for the C++ code I'm
working on right now.

Is http://www.microsoft.com/msj/0197/Exception/Exception.aspx with code:
int main()
{
DWORD handler = (DWORD)_except_handler;

__asm
{ // Build EXCEPTION_REGISTRATION record:
push handler // Address of handler function
push FS:[0] // Address of previous handler
mov FS:[0],ESP // Install new EXECEPTION_REGISTRATION
}

__asm
{
mov eax,0 // Zero out EAX
mov [eax], 1 // Write to EAX to deliberately cause a
fault
}

printf( "After writing!\n" );

__asm
{ // Remove our EXECEPTION_REGISTRATION record
mov eax,[ESP] // Get pointer to previous record
mov FS:[0], EAX // Install previous record
add esp, 8 // Clean our EXECEPTION_REGISTRATION off
stack
}

return 0;
}
 
J

James Kuyper

Użytkownik "James Kuyper said:
On the other hand: if your entire program never actually handles
exceptions, then you may be able to adequately emulate exceptions simply
by replacing throw() with exit(). That's the case for the C++ code I'm
working on right now.

Is http://www.microsoft.com/msj/0197/Exception/Exception.aspx with code:
int main()
{
DWORD handler = (DWORD)_except_handler;

__asm
{ // Build EXCEPTION_REGISTRATION record:
push handler // Address of handler function
push FS:[0] // Address of previous handler
mov FS:[0],ESP // Install new EXECEPTION_REGISTRATION
}

__asm
{
mov eax,0 // Zero out EAX
mov [eax], 1 // Write to EAX to deliberately cause a
fault
}

printf( "After writing!\n" );

__asm
{ // Remove our EXECEPTION_REGISTRATION record
mov eax,[ESP] // Get pointer to previous record
mov FS:[0], EAX // Install previous record
add esp, 8 // Clean our EXECEPTION_REGISTRATION off
stack
}

return 0;
}

Your title said "pure C". The __asm keyword is not pure C; nor is
anything that's microsoft-specific. There's nothing wrong with writing
microsoft-specific code, if you're willing to tie your code to
microsoft, but if you're willing to consider solutions of that type, you
should have changed the Subject: line accordingly, and you should have
posted your message to a forum specializing in programming for Win32.
 
B

Borneq

Użytkownik "James Kuyper said:
On 12/07/2012 10:40 AM, Borneq wrote:
Your title said "pure C". The __asm keyword is not pure C; nor is
anything that's microsoft-specific. There's nothing wrong with writing
microsoft-specific code, if you're willing to tie your code to
microsoft, but if you're willing to consider solutions of that type, you
should have changed the Subject: line accordingly, and you should have
posted your message to a forum specializing in programming for Win32.

Not exactly the I expressed what I have in mind. "Pure" - I think no C++ but
C, also assebler may be. It is interesting not only for Win32 (or Win64) but
also for Linux.
 
J

James Kuyper

Not exactly the I expressed what I have in mind. "Pure" - I think no C++ but
C, also assebler may be. It is interesting not only for Win32 (or Win64) but
also for Linux.

Well, if it includes a assembler, you should not describe it as "pure
C". It would be more accurate to describe it as "C plus assembler".
If you're interested in a single solution that works for Linux as well
as Win32, the one you found at that Microsoft web site isn't that solution.
 
I

Ian Collins

BGB said:
well, it is possible, either to use OS-specific mechanisms (like Win32
SEH), or write ones' own exception-handling system (potentially
involving linked-lists and longjmp), and rewrite any code to use this.

it is kind-of ugly, but it sort of works...

It would also be fraught with danger. Writing exception safe code in C
isn't easy.
 
K

Keith Thompson

Borneq said:
How can translate C++ to C code with exceptions handling? Unfortunately
Stroustrup translator cfron has only source and not compiled, llvm command
to translate C++ => C not works.

We can probably give you a better answer if you let us know *why*
you want to translate the C++ code to C. How does leaving the
code in C++ and compiling it with a C++ compiler not satisfy your
requirements?
 
B

Borneq

Uzytkownik "Keith Thompson said:
We can probably give you a better answer if you let us know *why*
you want to translate the C++ code to C. How does leaving the
code in C++ and compiling it with a C++ compiler not satisfy your
requirements?

I wanna for training reasons write compiler (rightly translator) from my own
object language to C+asm. It will be well if it support exceptions and
multiple Inheritance. No garbage collector - this language will be
traditional.
I try install llvm under Ubuntu:
sudo apt-get install llvm
sudo apt-get install clang
sudo apt-get install llvm-gcc-4.6
% llvm-g++ -emit-llvm x.cpp -o program.bc -c
% llc -march=c program.bc -o x.c
is error: llc: program.bc:1:1: error: expected top-level entity
also "lli program.bc" is error
 
J

James Kuyper

I wanna for training reasons write compiler (rightly translator) from my own
object language to C+asm.

How does that involve translation of C++ code to C?
... It will be well if it support exceptions and
multiple Inheritance.

Well, C has neither exceptions nor inheritance of any kind, much less
multiple inheritance. You might need to reconsider your plans. For
instance, why don't you target C++ + asm, rather than C + asm?
sudo apt-get install llvm
sudo apt-get install clang
sudo apt-get install llvm-gcc-4.6
% llvm-g++ -emit-llvm x.cpp -o program.bc -c

So, where did x.cpp come from, and what does it have to to with the
situation you described above?
% llc -march=c program.bc -o x.c
is error: llc: program.bc:1:1: error: expected top-level entity
also "lli program.bc" is error

If you want to know why you got that error message, a forum devoted to
llvm would be a better place to find out. You might need to explain the
contents of x.cpp in order to get a meaningful answer.
 
R

Rosario1903

U?ytkownik "James Kuyper said:
On the other hand: if your entire program never actually handles
exceptions, then you may be able to adequately emulate exceptions simply
by replacing throw() with exit(). That's the case for the C++ code I'm
working on right now.

Is http://www.microsoft.com/msj/0197/Exception/Exception.aspx with code:
int main()
{
DWORD handler = (DWORD)_except_handler;

__asm
{ // Build EXCEPTION_REGISTRATION record:
push handler // Address of handler function
push FS:[0] // Address of previous handler
mov FS:[0],ESP // Install new EXECEPTION_REGISTRATION

so here FS:[0] point to a region of mem that has in its first 4bytes
the address of the *previous* handler; right?
}

__asm
{
mov eax,0 // Zero out EAX
mov [eax], 1 // Write to EAX to deliberately cause a
fault
}

printf( "After writing!\n" );

__asm
{ // Remove our EXECEPTION_REGISTRATION record
mov eax,[ESP] // Get pointer to previous record
mov FS:[0], EAX // Install previous record
add esp, 8 // Clean our EXECEPTION_REGISTRATION off
stack
}

return 0;
}

what is one handler?
if it is one function, what arg it has? what it return?

this here crash...
__________
;nasmw -fobj that.asm
section _DATA use32 public class=DATA

global _fini
global _fend

dat dd 0, 0, 0, 0

section _TEXT use32 public class=CODE

; 0ra, 4P_address_hadler_function
_fini:
mov edx, dword[esp+ 4]
cmp edx, 0
jne .1
..e: mov eax, -1
stc
jmp short .z
..1: mov eax, [fs:0]
cmp eax, 0
je .e
mov [dat], eax ; store address of previos hf
mov [dat+4], edx ; store address of hf
mov ecx, dat
mov [fs:0], ecx
xor eax, eax
..z:
ret

_fend:
mov eax, [dat]
cmp eax, 0
je .z
mov [fs:0], eax
..z:
ret
__________
/*bcc32 -v this.c that.obj */
#include <stdio.h>

int fini(char* a);
int fend(void);
int except_handler(void){return 1;}

int main()
{unsigned a,b;

fini(except_handler);
a=0; b=9; b=b/a;
printf( "After writing! %u\n", b);

fend();

return 0;

}
 
B

BGB

It would also be fraught with danger. Writing exception safe code in C
isn't easy.

yes, but it can be done...

granted, using it is partly more about consistency though.


in my case, I have a mechanism which works in one of 2 ways:
on Win32, it hooks into SEH, and uses a special exception code;
on other targets (such as Linux), it uses TLS, linked lists, and
longjmp, basically to implement a sort of "fake SEH".

the external interface sort of crudely implements a system vaguely like
try/catch/finally in Java, just based around function calls (and if/else
blocks function-calls are basically used to implement the
try/catch/finally blocks).

granted, yes, it is kind of ugly and painful to use, and so for the most
part I ended up sticking to using return values to indicate error status.


when it came to the choice of whether my scripting language should throw
exceptions in C land for uncaught script exceptions, or just return an
error status, I ended up opting for an error status (with another API
call to optionally fetch the VM's exception object).

note that if the exception manages to unwind all the way without getting
caught anywhere, Win32 will give the message box and terminate the
program. IIRC, for the fake-SEH, it is rigged up to print an error
message and call "abort()" or similar.


or such...
 
B

Borneq

Użytkownik "Ian Collins said:
Neither. You have to buy the compiler.

Is problem - I need both Windows and Linux compiler, comeau sold only one,
two compilers will be too expensive
 
B

BartC

christian.bau said:
There are situations where it doesn't make sense to say "how do I do
this C++ thing in C"; the proper answer would be "just do it in C++".
Exception handling is one of those things.

Yet C++ was originally implemented in C?
When an exception is thrown, you have to clean up resources as the
exception winds its way through the call chain.

What sort of resources need to be cleaned up?

Local objects that would have been deallocated on a normal return are
understood. But what about more global/more persistent changes, where it's
not clear what the intentions of the intermediate function would have been?
In Java or C++ there
are things in the language that do this clean up automatically.
Without that, it is impossible for a mere human to always do that
cleanup correctly. Forget it.

It sounds like this C code will be created automatically, so there is plenty
of scope to add in all this capability, especially if performance isn't
important.
 
J

James Kuyper

What sort of resources need to be cleaned up?

The resources, if any, associated with objects with automatic storage
duration whose lifetime is ended by the throwing of the exception, or
which are released in catch{} blocks that match the thrown exception.
Local objects that would have been deallocated on a normal return are
understood. But what about more global/more persistent changes, where it's
not clear what the intentions of the intermediate function would have been?

The "intentions" of the intermediate function are, in C++, expressed in
two ways: the destructors of the objects that are local to that
function, and the code in the catch{} blocks that correspond to the
thrown exception. It's more than a little difficult to do that in C,
which has neither destructors nor catch{} blocks.
 
B

Borneq

Uzytkownik "James Kuyper said:
How does that involve translation of C++ code to C?
Well, C has neither exceptions nor inheritance of any kind, much less
multiple inheritance. You might need to reconsider your plans. For
instance, why don't you target C++ + asm, rather than C + asm?

I compile with http://llvm.org/demo/index.cgi
and it call:
__cxa_allocate_exception
__cxa_throw
__cxa_begin_catch
__cxa_end_catch
how it call in own program?
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top