I am using setjmp and longjmp for the first time, and I ran across an issue that comes about when I wrap setjmp and longjmp. I boiled the code down to the following example:
#include <stdio.h>
#include <setjmp.h>
jmp_buf jb;
int mywrap_save()
{
int i = setjmp(jb);
return i;
}
int mywrap_call()
{
longjmp(jb, 1);
printf("this shouldn't appear\n");
}
void example_wrap()
{
if (mywrap_save() == 0){
printf("wrap: try block\n");
mywrap_call();
} else {
printf("wrap: catch block\n");
}
}
void example_non_wrap()
{
if (setjmp(jb) == 0){
printf("non_wrap: try block\n");
longjmp(jb, 1);
} else {
printf("non_wrap: catch block\n");
}
}
int main()
{
example_wrap();
example_non_wrap();
}
Initially I thought example_wrap() and example_non_wrap() would behave the same. However, the result of running the program (GCC 4.4, Linux):
wrap: try block
non_wrap: try block
non_wrap: catch block
If I trace the program in gdb, I see that even though mywrap_save() returns 1, the else branch after returning is oddly ignored. Can anyone explain what is going on?
The longjmp() routines may not be called after the routine which called
the setjmp() routines returns.
In other words, you are screwing up your stack.
You might take a look at the assembly to see if you can piece together what's really happening.
setjmp() will save the current call stack and mark a point. When the call stack grows, no matter how far from the marked point, you can use longjmp() to go to the marked point, like you never left the point.
In your code, when returning from mywrap_save(), the marked point was no longer valid, the stack space around the point was dirty, hence you cannot go back to a dirty point.
Related
In C, I know it is good practice to always check if a newly malloced variable is null right after allocating. If so, I can output an error e.g. perror and exit the program.
But what about in more complicated programs? E.g. I have main call a function f1(returns an int), which calls a function f2(returns a char*), which calls a function f3(returns a double), and I fail to malloc inside f3.
In this case, I can't seem to just output an error and exit(and may even have memory leaks if possible) since f3 will still force me to first return a double. Then f2 will force me to return a char*, etc. In this case, it seems very painful to keep track of the errors and exit appropriately. What is the proper way to efficiently cover these sort of errors accross functions?
The obvious solution is to design your program with care, so that every function that does dynamic allocation has some means to report errors. Most often the return value of the function is used for this purpose.
In well-designed programs, errors bounce back all the way up the call stack, so that they are dealt with at the application level.
In the specific case of dynamic memory allocation, it is always best to leave the allocation to the caller whenever possible.
It's always a problem. You need a disiplined approach.
Firstly, every dynamic pointer must be "owned" by someone. C won't help you here, you just have to specify. Generally the three patterns are
a) Function calls malloc(), then calls free():
b) We have two matching functions, one which returns a buffer or dynamic
structure, one which destroys it. The function that calls create also calls the destroy.
c) We have a set of nodes we are inserting into a graph, at random throughout the program. It needs to be managed like b, one function creates the root, then calls the delete which destroys the entire graph.
The rule is owner holds and frees.
If you return a pointer, return 0 on out of memory. If you return an integer, return -1. Errors get propagated up until some high level code knows what user-level operation has failed and aborts it.
The other answers are correct that the correct way to handle this is to make sure that every function that can allocate memory can report failure to its caller, and every caller handles the possibility. And, of course, you have a test malloc shim that arranges to test every possible allocation failure.
But in large C programs, this becomes intractable — the number of cases that need testing increases exponentially with the number of malloc callsites, for starters — so it is very common to see a function like this in a utils.c file:
void *
xmalloc(size_t n)
{
void *rv = malloc(n);
if (!rv) {
fprintf(stderr, "%s: memory exhausted\n", program_name);
exit(1);
}
return rv;
}
All other code in the program always calls xmalloc, never malloc, and can assume it always succeeds. (And you also have xcalloc, xrealloc, xstrdup, etc.)
Libraries cannot get away with this, but applications can.
The one way to switch across the functions is exception handling.
When an exception is thrown, it return the scope the catch part.
But make sure of the memory allocation across the functions, Since it directly moves to the catch blok.
The sample code for reference,
// Example program
#include <iostream>
#include <string>
using namespace std ;
int f1()
{
int *p = (int*) malloc(sizeof(int)) ;
if(p == NULL)
{
throw(1) ;
}
//Code flow continues.
return 0 ;
}
char *g()
{
char *p ;
f1() ;
cout << "Inside fun g*" << endl ;
return p;
}
int f2()
{
g() ;
cout << "Inside fun f2" << endl ;
return 0 ;
}
int main()
{
try
{
f2() ;
}
catch(int a)
{
cout << "Caught memory exception" << endl ;
}
return 0 ;
}
Hi I want to ask about setjmp/longjmp. I tried to search, but I was unsucessuful...
#include <stdio.h>
#include <setjmp.h>
jmp_buf a, b;
void jump() {
int aa = setjmp(a);
if (aa)
{
printf("Jump!\n");
}
else
{
longjmp(b, 1);
printf("Should not happened...\n");
}
printf("End of function!\n");
}
int main(int argc, char** argv) {
int bb = setjmp(b);
if (bb)
{
longjmp(a, 1);
printf("Should not happened...\n");
}
else
{
jump();
printf("What here?\n");
}
printf("Exit\n");
return 0;
}
The question is, what will happen after last printf in jump()... I tried this code and it turned into infinite loop. Why? I though that setjmp will store environment data, so the jump function shall return after it's original call... I'm quiet confused. Thanks for reply :)
The whole program has undefined behavior.
setjmp(b); stores the stack state.
jump() is called.
`setjmp(a);' stores the stack state again.
longjmp(b, 1); restores the stack to the point before jump() was ever called. So the state stored in a is now invalid.
Execution continues at the if in main().
longjmp(a, 1); is called. Ouch. This causes undefined behavior due to 4 above.
Your confusion probably results from the slightly imprecise use of the world "return" in the Linux docs for setjmp().
The stack context will be invalidated if the function which called setjmp() returns.
In your example, the function jump() didn't return in the normal way, but the effect was the same: the stack was "chopped" by the first longjmp() to the state before jump(), which is what a return does, too.
This is mostly theoretical question as there's not much use in it.
consider this situation :
function a() {
return;
}
function b(){
a();
}
Can you invoke a return in a parent function from a child one?
Now in this case you can simpley do return a(); and that will happen but let's say you're intrested of not preforming a return.
I know that when translating it to assembly this doesn't make sense, in this case u can use goto but we all know how dangerous that is.
My logic says that if you can preform a continue from a child loop that will invoke continue on the parent, this should be the same, but loops doesn't affect the stack so it makes sense that continue does work.
I am wondering if there's any way to handle this case witjout using events or the oop approach?
The traditional C solution is the longjmp function, which can jump an arbitrary way up the stack. Mind you, there have always been people who were wise enough not to use it, and it has been largely succeeded by exception handling.
You could use a macro instead of a function.
#define a() ... return ...
A use case would be asserts that are not completely removed in a release build, but abort a function:
#define REQUIRE(x) do { assert((x)); if (!(x)) return; } while (0)
You can also hack something in assembler to get the stackframe of the calling functions and use the return address from there:
void return2(){
void * frame;
#if (defined(x86_64) || defined(__x86_64__))
__asm__(
"pop %rbp\n" //skip over stack frame of return2
"mov %rsp, %rbp\n"
"pop %rax\n"
"pop %rbp\n" //skip over stack frame of caller
"mov %rsp, %rbp\n"
"pop %rax\n"
);
#else
#error only implmented for amd64...
#endif
}
Then
void a(){
printf("a 0\n");
return2();
printf("a 1\n");
}
void b(){
printf("b 0\n");
a();
printf("b 1\n");
}
int main(int argc, char* argv[])
{
printf("main 0\n");
b();
printf("main 1\n");
return 0;
}
prints
main 0
b 0
a 0
main 1
This is the most dangerous solution from all (and it fails if gcc inlines something or removes the stackframe at higher optimization levels. But you could add a check that examines the instructions, if they were optimized )
If you are on Windows using MSVC, you can use exceptions (Strucured Exception Handling, SEH) to achive something similar. On other platforms you can use setjmp/longjmp, as thiton said.
With SEH, you could do something like the following (haven't tried it since I have no Windows with Visual Studio ready):
#include "stdio.h"
#include "Windows.h"
void func_b() {
printf("In func_b()\n");
// return safely to main
RaiseException(1, EXCEPTION_NONCONTINUABLE, 0, NULL);
printf("At end of func_b()\n");
}
void func_a() {
printf("In func_a()\n");
func_b();
printf("At end of func_a()\n");
}
void main() {
printf("In func_a()\n");
__try {
func_a();
}
__except (GetExceptionCode() == 1) {
printf ("Early return to main()\n");
}
printf("At end of main()\n");
}
The RaiseException call causes control to go up the stack until the exception is caught, in main(). This is not really "return^2", because the calling function (main) has to play along. In general, you'll also need cooperation of the functions you want to jump through (here func_a), since they might do stuff and need cleanup. Just saying "return from func_b, and stop whatever func_a was doing and return from that, too" can be very dangerous. If you use exceptions, however, you can wrap your code in func_a in try/finally clause:
FILE* f;
__try {
f = fopen("file.txt", "r");
func_b();
}
__finally {
fclose(f);
printf("Cleanup for func_a()\n");
}
This is of course much nicer in languages that natively support exceptions (C++, Python, Java, ...), and don't just have it bolted on as a proprietary extension.
Note that some people regard it as bad practice to use exceptions for control flow, and say exceptions should be reserved for truely exceptional events (like IO errors). There are a buch of cases where it does make sense (e.g. you're parsing something, and realize deep down the stack that you have to rewind and parse something differently, you can throw a custom exception). In general, I'd say try not to be too clever, and try not to do things that will confuse readers of your program. When it seems you need to use some trick like this, there's often a way to restructure the program to do it in a way that's natural for the language. Or maybe the language your using is not a good choice for the problem.
Given this code :
#include <stdio.h>
#include <assert.h>
void print_number(int* somePtr) {
assert (somePtr!=NULL);
printf ("%d\n",*somePtr);
}
int main ()
{
int a=1234;
int * b = NULL;
int * c = NULL;
b=&a;
print_number (c);
print_number (b);
return 0;
}
I can do this instead :
#include <stdio.h>
#include <assert.h>
void print_number(int* somePtr) {
if (somePtr != NULL)
printf ("%d\n",*somePtr);
// else do something
}
int main ()
{
int a=1234;
int * b = NULL;
int * c = NULL;
b=&a;
print_number (c);
print_number (b);
return 0;
}
So , what am I gaining by using assert ?
Regards
assert is to document your assumptions in the code. if statement is to handle different logical scenarios.
Now in your specific case, think from the point of view of the developer of the print_number() function.
For example when you write
void print_number(int* somePtr) {
assert (somePtr!=NULL);
printf ("%d\n",*somePtr);
}
you mean to say that,
In my print_number function I assume that always the pointer coming is not null. I would be very very surprised if this is null. I don't care to handle this scenario at all in my code.
But, if you write
void print_number(int* somePtr) {
if (somePtr != NULL)
printf ("%d\n",*somePtr);
// else do something
}
You seem to say that, in my print_number function, I expect people to pass a null pointer. And I know how to handle this situation and I do handle this with an else condition.
So, sometimes you will know how to handle certain situations and you want to do that. Then, use if.
Sometimes, you assume that something will not happen and you don't care to handle it. You just express your surprise and stop your program execution there with assert.
The difference is that assert is enabled only for debug build; it is not enabled for release build (i.e when NDEBUG is defined), which means in the release build there will be no check; as a result, your code will be little bit faster, compared to the one in which you use if condition which remains in the release build as well.
That means, assert is used to check common errors when you write the code, and catch them as soon as possible, in the development phase itself.
Lots of reasons:
Asserts are usually removed for release builds.
Asserts will report failure information to the client. if() does nothing by itself.
Because asserts are usually macros, you can also get code information about the failing assertion.
Assert is more semantically clear than if().
If assertion fails, you will see the output containing the failed assertion itself, plus the function and the line of the failed assert, something like:
test: main.cpp:9: int main(): Assertion `0==1' failed.
So, if your program crashes in runtime, you will see the exact reason and location of the crash.
There's a big article about assertions in wiki.
Assert will inform you that something wrong happend, possibly error to be fixed. In debug mode it will break and show callstack that will help you with fixing bug. So its a good practice to use. I would actually use if() and assert, because in Release your asserts should be turned off:
void print_number(int* somePtr) {
assert(somePtr != NULL);
if (somePtr != NULL)
printf ("%d\n",*somePtr);
// else do something
}
in " // else do something " you might think of throwing exception or returning error code.
Listen If Your (if) statement becomes True or False so compiler go for the next instructions.
But in assert.h when your statement becomes false "Program Terminates immediately" with assertion message.
EXAMPLE :*
#include <assert.h> #include <stdio.h>
int main () {
int a;
printf("Enter an integer value: "); scanf("%d", &a); assert(a >= 10);
printf("Integer entered is %d\n", a);
return(0); }
I typed this into Google, but I only found how-tos in C++.
How can I do it in C?
There are no exceptions in C. In C the errors are notified by the returned value of the function, the exit value of the process, signals to the process (Program Error Signals (GNU libc)) or the CPU hardware interruption (or other notification error form the CPU if there is)(How processor handles the case of division by zero).
Exceptions are defined in C++ and other languages though. Exception handling in C++ is specified in the C++ standard "S.15 Exception handling", there is no equivalent section in the C standard.
In C you could use the combination of the setjmp() and longjmp() functions, defined in setjmp.h. Example from Wikipedia
#include <stdio.h>
#include <setjmp.h>
static jmp_buf buf;
void second(void) {
printf("second\n"); // prints
longjmp(buf,1); // jumps back to where setjmp
// was called - making setjmp now return 1
}
void first(void) {
second();
printf("first\n"); // does not print
}
int main() {
if ( ! setjmp(buf) ) {
first(); // when executed, setjmp returns 0
} else { // when longjmp jumps back, setjmp returns 1
printf("main"); // prints
}
return 0;
}
Note: I would actually advise you not to use them as they work awful with C++ (destructors of local objects wouldn't get called) and it is really hard to understand what is going on. Return some kind of error instead.
There's no built-in exception mechanism in C; you need to simulate exceptions and their semantics. This is usually achieved by relying on setjmp and longjmp.
There are quite a few libraries around, and I'm implementing yet another one. It's called exceptions4c; it's portable and free. You may take a look at it, and compare it against other alternatives to see which fits you most.
Plain old C doesn't actually support exceptions natively.
You can use alternative error handling strategies, such as:
returning an error code
returning FALSE and using a last_error variable or function.
See http://en.wikibooks.org/wiki/C_Programming/Error_handling.
C is able to throw C++ exceptions. It is machine code anyway.
For example, in file bar.c:
#include <stdlib.h>
#include <stdint.h>
extern void *__cxa_allocate_exception(size_t thrown_size);
extern void __cxa_throw (void *thrown_exception, void* *tinfo, void (*dest) (void *) );
extern void * _ZTIl; // typeinfo of long
int bar1()
{
int64_t * p = (int64_t*)__cxa_allocate_exception(8);
*p = 1976;
__cxa_throw(p, &_ZTIl, 0);
return 10;
}
In file a.cc,
#include <stdint.h>
#include <cstdio>
extern "C" int bar1();
void foo()
{
try
{
bar1();
}
catch(int64_t x)
{
printf("good %ld", x);
}
}
int main(int argc, char *argv[])
{
foo();
return 0;
}
To compile it:
gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out
Output
good 1976
https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html has more detail info about __cxa_throw.
I am not sure whether it is portable or not, and I test it with 'gcc-4.8.2' on Linux.
This question is super old, but I just stumbled across it and thought I'd share a technique: divide by zero, or dereference a null pointer.
The question is simply "how to throw", not how to catch, or even how to throw a specific type of exception. I had a situation ages ago where we needed to trigger an exception from C to be caught in C++. Specifically, we had occasional reports of "pure virtual function call" errors, and needed to convince the C runtime's _purecall function to throw something. So we added our own _purecall function that divided by zero, and boom, we got an exception that we could catch on C++, and even use some stack fun to see where things went wrong.
On Windows with Microsoft Visual C++ (MSVC) there's __try ... __except ..., but it's really horrible and you don't want to use it if you can possibly avoid it. Better to say that there are no exceptions.
C doesn't have exceptions.
There are various hacky implementations that try to do it (one example at: http://adomas.org/excc/).
As mentioned in numerous threads, the "standard" way of doing this is using setjmp/longjmp. I posted yet another such solution to https://github.com/psevon/exceptions-and-raii-in-c
This is to my knowledge the only solution that relies on automatic cleanup of allocated resources. It implements unique and shared smartpointers, and allows intermediate functions to let exceptions pass through without catching and still have their locally allocated resources cleaned up properly.
C doesn't support exceptions. You can try compiling your C code as C++ with Visual Studio or G++ and see if it'll compile as-is. Most C applications will compile as C++ without major changes, and you can then use the try... catch syntax.
If you write code with the happy path design pattern (for example, for an embedded device) you may simulate exception error processing (AKA deffering or finally emulation) with operator "goto".
int process(int port)
{
int rc;
int fd1;
int fd2;
fd1 = open("/dev/...", ...);
if (fd1 == -1) {
rc = -1;
goto out;
}
fd2 = open("/dev/...", ...);
if (fd2 == -1) {
rc = -1;
goto out;
}
// Do some with fd1 and fd2 for example write(f2, read(fd1))
rc = 0;
out:
//if (rc != 0) {
(void)close(fd1);
(void)close(fd2);
//}
return rc;
}
It is not actually an exception handler, but it takes you a way to handle error at function exit.
P.S.: You should be careful to use goto only from the same or more deep scopes and never jump a variable declaration.
Implementing exceptions in C by Eric Roberts.
Chapter 4 of C Interfaces and Implementations by Hanson.
A Discipline of Error Handling by Doug Moen
Implementing Exceptions in C (details the article of E. Roberts)
In C we can't use try case to handle the error.
but if you can use Windows.h so you can:
#include <stdio.h>
#include <Windows.h>
#include <setjmp.h>
jmp_buf Buf;
NTAPI Error_Handler(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
printf("co loi roi ban oi.!!!\r\n");
longjmp(Buf, 1);
}
void main()
{
AddVectoredExceptionHandler(1, Error_Handler);
int x = 0;
printf("start main\r\n");
if (setjmp(Buf) == 0)
{
int y = 1 / x;
}
printf("end main\r\n");
}