I'm working on a framework on C language, for it I want to implement exceptions, for it I'm using longjump with setjump, but on x64 machines longjump still outputs an integer.
I've created a class (struct with vptr essentially), which represents exception, but to throw it out in code I need to throw a pointer to this structure. The pointer has an unsigned long long value (qword) for x64 machines and unsigned int (dword) for x86, so I shall require only qword to be in output to handle the error.
Are there implementations of longjmp and setjmp, which can output qword?
Or maybe I could write my own longjump, but for it the original source code is required.
You can enclose your jmp_buf-typed variable in a larger structure, possibly larger by just sizeof(void*). Then just before calling longjmp() you can store the pointer in that extra space. There's no need to try to squeeze a pointer into an int.
Example:
#include <stdio.h>
#include <setjmp.h>
struct jmp_buf_struct
{
jmp_buf jb;
void* exc_ptr;
};
void may_throw(jmp_buf jb)
{
struct jmp_buf_struct* jbs_ptr = (struct jmp_buf_struct*)jb;
jbs_ptr->exc_ptr = "Exception message!";
longjmp(jb, 1);
}
int main()
{
struct jmp_buf_struct jbs;
if (setjmp(jbs.jb))
{
printf("Threw %p = \"%s\".", jbs.exc_ptr, (char*)jbs.exc_ptr);
}
else
{
may_throw(jbs.jb);
puts("Didn't throw.");
}
return 0;
}
Output:
Threw 0x55638ebc78c4 = "Exception message!".
If you want to be portable, then you can use array indexes, to an array where you store all the 64bit pointers (or simply an array of pointers to structures with pages of information about what to do on some exception).
How do you populate such an array is another question. Of course you don't need to populate the array with all the instances that can become an exception, only with the ones you have try-ed and are able to catch. But probably you will need more than just a pointer (as you have to deal with the runtime case in which you have the same exception, catched in multiple active places in your stack.)
Once you solve the above problem, probably you can even use a short int for the thing, once you have understood the nature of the problem you need to solve.
Based on reading the comments, I see you comment that a global variable is not suitable because of multithreading concerns. First, you can have it global, in the context of the thread (as e.g. the errno variable), as that's the reason of using a void * to call the routine the thread executes, and returns back once finished. You can have it there, private to thread global data.
On a second point, if you want to manage such strange things from the point of view of C, as manipulating the stack in weird ways, the functions mentioned do (I don't believe you know completely how the internals of setjmp()/longjmp() work.) I can tell you that the setjmp()/longjmp() api was written a long of time ago (in the range of 50 years now), in the times of old V6 unix code, to cope with unknown unix device drivers error processing ---a very controlled and simple environment---) simply, the use of longjmp() is far more complicated (and strongly discouraged, even by their authors K & R) than switching to a different language (like the suggested C++) that fully supports exceptions in its core (this recommendation is not mine, it has been suggested in the comments to your question)
Third. If you use setjmp() and longjmp() you need to know also that they (both) use the calling thread's stack to mark the pointer and the where to go to store the information. So, you have to control, for example, that if you do a longjmp() in a signal handler, you can severely destroy the stack of the thread executing the signal handler (which is the one that got interrupted by the signal) if it is not the same thread as the one who did the setjmp() call. The reason for this is that the thread interrupted will switch its stack with the one of the thread that did the setjmp() and both threads will begin executing code with the same stack at different points, this jumps back to the time of implementation of both functions (there was only a pdp computer available, no multiple cpus/cores as it is common today, so there was only a stack) You have to be specially careful here, because normally, the thread that generates the exception is the same that the places to catch it, but this can be false for asynchronous traps, like signal processing.
By the way, what you are doing is very interesting, and will allow you to know how a language implements internally complex behaviours like exception processing. I applause you for your courage on trying this kind of things, and don't hesitate, that if you need a mentor in C++ I'll be available for you.
Just don't give up!!
Related
I'm trying to understand basics of C, volatile keyword exactly.
It doesn't seem to work as I thought.
I read somewhere:
volatile specifies that value associated with the var can be modified by action
other than those in the nearby code.
When a var is declared volatile, the compiler reloads the value from
memory each time it is accessed by the program.
This prevents optimization by optimizing compilers.
It's mainly used to ensure predictable program behavior.
I've got two programs, compiled from two different .c files.
start_loop has global int variable called done with 0 as initial value and infinite loop which should test if done value have been changed to 1. Also it outputs address of the done variable to stdout.
start_loop program:
#include <stdio.h>
#include <time.h>
volatile int done = 0;
void delay(int seconds){
// some logic for time delay here
}
void main() {
while (done !=1){
delay(4);
printf("adress of `done`: %p\nvalue: %d\n", &done, done);
}
}
And change_done_var_value program which should get the address of the done variable as main argument and change it from 0 to 1.
Thus infinite loop in start_loop program should check value of done and exit the program.
change_done_var_value:
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
char *str_arg_done = argv[1];
long int done_addr = (int)strtol(str_arg_done, NULL, 16);
long int *done = (long int *)done_addr; // converting str to pointer
printf("got the address as first arg(str): %s -> address/value %p/%li\n", argv[1], done, *done);
printf("change `done` to 1?\n");
char answer = fgetc(stdin);
if (answer == 'y')
{
*done = 1;
printf("changed\nnew value: %li", *done);
}
else
{
printf("canceled\n");
}
As i've started the start_loop program in first terminal tab i got:
4 seconds delay passed
#1
adress of `done`: 0x601048
value: 0
4 seconds delay passed
#2
adress of `done`: 0x601048
value: 0
...
In the second terminal tab i started the change_done_var_value and passed 0x601048 to it:
got the address as first arg(str): 0x601048 -> adress/value 0x601048/0
change `done` to 1?
y
changed
new value: 1
But start_loop program still runs:
4 seconds delay passed
#46
adress of `done`: 0x601048
value: 0
It seems that the change_done_var_value program got the right address value cause it shows right 0 value while dereferencing pointer to done variable..
What do i need to do to make things work(to change value of done from change_done_var_value and stop the executing of thestart_loop program)?
Or it doesn't work like this..
action other than those in the nearby code
Yes; this means things that are able to modify the corresponding chunk of memory. Most often, this will be a different thread within the same program. In some very specific platform-specific circumstances, you might arrange for a variable to be in a specific location that has a special meaning to the OS (or to the hardware); for example, on an old handheld or console you could read from a virtual memory location that represents an I/O register, in order to learn what button was pressed on the keypad. By using volatile, the compiler will understand that the value has to be checked, because the hardware may have written to that memory and your program depends on knowing about the change.
On a modern desktop computer, programs have memory protection and memory space virtualization. They cannot easily look at each others' data, and will typically need some special arrangement/permission to do so. But even when it is possible, you cannot simply check on the other program's variable by using its name - the name is only meaningful to the compiler; it is not an actual part of the compiled program (although a debug-mode compilation might try to make it behave that way a little bit).
If I understand right, you try to use memory from one program in another program? "It doesn't work like this" on any modern operating system because programs (or better: "processes") are encapsulated purposefully this way that they can't access the memory of other processes without operating-system-specific interprocess communication library functions. You can read more about them and how to use them in C in a Linux-based operating system on this website:
Linux Interprocess Communications
I'm sorry that I can't elaborate further since I never used internal interprocess communication on a common Desktop Operating System yet.
There is also a more heavy-weight option to use the socket API (which generally can be used even accross a network of distinct PCs all over the world). Using the socket API is not difficult and is taught in network lecture courses in university. You then get "server" and "client" programs and you have to take care about some "primitives" which must be called in a specific order.
A common source of tutorials seems to be the Beej Guide .
This protection mechanism is called memory virtualization. It makes that every process uses its very own virtual address space which is not equal to the one of other processes. Or brief: the same addresses in different programs will lead to separate physical addresses in the real memory.
In my opinion the design mistake here is to compile two different programs to achieve the task. The usual appraoch would be to compile only one single program which uses multi-threading (that means multiple threads of execution) because multi-threading is more light-weight than interprocess communication and maybe easier to use (at least I know how to do it). For multi-threading, you can use the pthread library in Linux-based systemes which can be included into your program with the -pthread command line option when I remember correctly).
Happy coding!
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Is it possible to do something like this in GCC?
void foo() {
if (something()) returnSomewhereElse;
else return;
}
void bar() {
foo();
return; // something failed, no point of continuing
somewhereElse:
// execution resumes here if something succeeds
// ...
}
can this be achieved in a portable way, using C and GCC extensions, without using platform specific assembly?
the stack state will not change between the normal and altered return points, so is it possible to reuse the code that restores the stack and registers state from the regular return?
considering that the function may or may not be inlined, if called it must alter the return address, if inlined it must only alter the code path but not the current function return address, as that would break the code
the alternate return point does not need to be a label, but I am hoping GCC's address of label extension can come in handy in this situation
Just to clarify the intent - it is about error handling. This example is a minimal one, just to illustrate things. I intend to use that in a much deeper context, to stop execution if an error occurs. I also assume the state doesn't change, which I may be wrong about, because there are no extra local variables added between the two return points, so I was hoping the code generated by the compiler to do that on foo's return can be reused for that and save the overhead of using longjmp, setting and passing the jump buffers.
The example "does make sense" because its intent is to show what I want to achieve, not why and how it would make sense in actual code.
Why is your idea simpler of better then simply returning a value from
foo() and having bar() either return or execute somewhereElse:
conditionally?
It is not simpler, and what you suggest is not applicable in practice, only in the context of a trivial example, but it is better because:
1 - it doesn't involve an additional returning of a value
2 - it doesn't involve an additional checking of a value
3 - it doesn't involve an additional jump
I am probably incorrectly assuming the goal should be clear at this point, and after all the clarifications and explanations. The idea is to provide an "escape code path" from a deep call chain without any additional overhead. By reusing the code the compiler has generated to restore the state of the previous call frame and simply modify the instruction at which execution resumes after the function returns. Success skips the "escape code path", the first error that occurs enters it.
if (failure) return; // right into the escape code path
else {
doMagickHere(); // to skip the escape code path
return; // skip over the escape code path
}
//...
void bar() {
some locals;
foo();
// enter escape code path here on foo failure so
destroy(&locals); // cleanup
return; // and we are done
skipEscapeCodePath: // resume on foo success
// escape path was skipped so locals are still valid
}
As for the claims made by Basile Starynkevitch that longjmp is "efficient" and that "Even a billion longjmp remains reasonable" - sizeof(jmp_buf) gives me a hefty 156 bytes, which is apparently the space needed to save pretty much all registers and a bunch of other stuff, so it can later be restored. Those are a lot of operations, and doing that a billion times is far, far outside of my personal understandings of "efficient" and "reasonable". I mean a billion jump buffers themselves are over 145 GIGABYTES of memory alone, and then there is the CPU time overhead as well. Not a whole lot of systems out there which can even afford that kind of "reasonable".
No, this is not possible portably, and I'm not sure to guess exactly what you want to achieve.
Terminology
Perhaps you want some non-local jump. Read carefully about setjmp.h, coroutines, call stack, exception handling, continuations, and continuation-passing-style. Understanding what call/cc is in Scheme should be very beneficial.
setjmp and longjmp
setjmp and longjmp are standard C99 functions (and they are quite fast, because the saved state is actually quite small). Be quite careful when you use them (in particular to avoid any memory leak). longjmp (or the related siglongjmp in POSIX) is the only way in portable standard C99 to escape from some function and get back into some caller.
The idea is to provide an "escape code path" from a deep call chain without any additional overhead
This is exactly the role of longjmp with setjmp. Both are quick, constant-time, operations (in particular unwinding a call stack of many thousands of call frames with longjmp takes a short and constant time). The memory overhead is practically one local jmp_buf per catch point, not a big deal. The jmp_buf is rarely put outside of the call stack.
A common way to use efficiently them would be to put the setjmp-ed jmp_buf in a local struct (so in your call frame) and pass the pointer to that struct to some internal static function(s) which indirectly would call longjmp on error. Hence setjmp and longjmp can, with wise coding conventions, mimic quite well and efficiently the complex semantics of C++ exception throwing and handling (or of Ocaml exceptions, or of Java exceptions, which both have a different semantics than C++). They are portable basic bricks enough for such a purpose.
Practically speaking, code something like:
struct my_foo_state_st {
jmp_buf jb;
char* rs;
// some other state, e.g a ̀ FILE*` or whatever
};
/// returns a `malloc̀ -ed error message on error, and NULL on success
extern const char* my_foo (struct some_arg_st* arg);
The struct my_foo_state_st is the private state. The my_foo is the public function (which you would declare in some public header). You did document (at least in the comment) that it returns a heap allocated error message on failure, hence the caller is responsible for freeing it. On success, you documented that it returns NULL. Of course, you could have other conventions and other arguments and/or result.
We declare and implement now an error function which is printing the error message into the state and escapes with a longjmp
static void internal_error_printf (struct my_foo_state*sta,
int errcode,
const char *fmt, ...)
__attribute__((noreturn, format(printf(2,3))));
void internal_error_printf(struct my_foo_state*sta,
int errcode, const char *fmt, ...) {
va_arg args;
va_start(args, fmt);
vasprintf(&sta->rs, fmt, args);
va_end(args);
longjmp(sta->jb, errcode);
}
We now have several possibly complex and recursive functions doing the bulk of the work. I only sketch them, you know what you want them to do. Of course you might want to give them some additional arguments (that is often useful, and it is up to you).
static void my_internal_foo1(struct my_foo_state_st*sta) {
int x, y;
// do something complex before that and compute x,y
if (SomeErrorConditionAbout(sta))
internal_error_printf(sta, 35 /*error code*/,
"errror: bad x=%d y=%d", x, y);
// otherwise do something complex after that, and mutate sta
}
static void my_internal_foo2(struct my_foo_state_st*sta) {
// do something complex
if (SomeConditionAbout(sta))
my_internal_foo1(sta);
// do something complex and/or mutate or use `sta`
}
(even if you have dozens of internal functions like above, you don't consume a jmp_buf in any of them; and you could also recurse quite deeply in them. You just need to pass a pointer -to struct my_foo_state_st in all of them, and if you are single-threaded and don't care about reentrancy, you could store that pointer in some static variable... or some thread-local one, without even passing it in some argument, which I find still preferable -since more re-entrant and thread friendly).
At last, here is the public function: it sets up the state and do a setjmp
// the public function
const char* my_foo (struct some_arg_st* arg) {
struct my_state_st sta;
memset(&sta, 0, sizeof(sta));
int err = setjmp(sta->jb);
if (!err) { // first call
/// put something in `sta` related to ̀ arg̀
/// start the internal processing
//// later,
my_internal_foo1(&sta);
/// and other internal functions, possibly recursive ones
/// we return NULL to tell the caller that all is ok
return NULL;
}
else { // error recovery
/// possibly release internal consumed resources
return sta->rs;
};
abort(); // this should never be reached
}
Notice that you can call your my_foo a billion times, it will not consume any heap memory when not failing, and the stack will grow by a hundred of bytes (released before returning from my_foo). And even if it failed a billion times by your private code calling a billion times the internal_error_printf no memory leak happens (because you documented that my_foo is returning an error string which the caller should free) if coding properly.
Hence using properly setjmp and longjmp a billion times does not eat a lot of memory (only a few hundred bytes on the call stack for one single local jmp_buf, which is popped on the my_foo function return). Indeed, longjmp is slightly more costly than a plain return (but it does the escape that return does not), so you would prefer to use it on error situations.
But using setjmp and longjmp is tricky but efficient and portable, and makes your code difficult to understand as documented by setjmp. It is important to comment it quite seriously. Using these setjmp and longjmp cleverly and wisely does not require "gigabytes" of RAM, as wrongly said in the edited question (because you consume only one single jmp_buf on the call stack, not billions of them). If you want more sophisticated control flow, you'll use a local jmp_buf at each and every dynamic "catch point" in the call stack (and you'll probably have a dozens of them, not billions). You'll need millions of jmp_buf only in the hypothetical case of a recursion of several millions call frames, each being a catch point, and that is not realistic (you'll never have a recursion of a depth of one million, even without any exception handling).
See this for a better explanation of setjmp for "exception" handling in C (and SFTW for other ones). FWIW, Chicken Scheme has a very inventive usage of longjmp and setjmp (related to garbage collection and to call/cc !)
Alternatives
setcontext(3) was perhaps POSIX but is now obsolete.
GCC has several useful extensions (some of them understood by Clang/LLVM) : statement exprs, local labels, labels as values and computed goto, nested functions, constructing function calls, etc.
(My feeling is that you are misunderstanding some concepts, notably the precise role of the call stack, so your question is very unclear; I gave some useful references)
returning a small struct
Notice also that on some ABIs, notably x86-64 ABI on Linux, returning a small struct (e.g. of two pointers, or of one pointer and one int or long or intptr_t number) is extremely efficient (since both pointers or integers go thru registers), and you could take advantage of that: decide that your function returns a pointer to the primary result and some error code, both packed in a single small struct:
struct tworesult_st {
void* ptr;
int err;
};
struct towresult_st myfunction (int foo) {
void* res = NULL;
int errcode = 0;
/// do something
if (errcode)
return (struct tworesult_st){NULL, errcode};
else
return (struct tworesult_st){res, 0};
}
On Linux/x86-64 the code above is optimized (when compiled with gcc -Wall -O) to return in two registers (without any stack consumed for the returned struct).
Using such a function is simple and very efficient (no memory involved, the two member ̀ struct` will be passed in processor registers) and could be as simple as:
struct tworesult_st r = myfunction(34);
if (r.err)
{ fprintf(stderr, "myfunction failed %d\n", r.err); exit(EXIT_FAILURE); }
else return r.ptr;
Of course you could have some better error handling (it is up to you).
Other hints
Read much more about semantics, in particular operational semantics.
If portability is not the major concern, study the calling conventions of your system and its ABI and the generated assembler code (gcc -O -Wall -fverbose-asm foo.c then look inside foo.s) , and code the relevant asm instructions.
Perhaps libffi could be relevant (but I still don't understand your goals, only guessed them).
You could try using label exprs and computed gotos, but unless you understand the generated assembler code, the result might not be what you expect (because the stack pointer changes at function calls and returns).
Self-modifying code is frowned upon (and "impossible" in standard C99), and most C implementations put the binary code in a read-only code segment. Read also about trampoline functions. Consider perhaps JIT compiling techniques, à la libjit, asmjit, GCCJIT.
(I firmly believe that the pragmatical answer to your concerns is either longjmp with suitable coding conventions, or simply returning a small struct; both can be used portably in a very efficient way, and I cannot imagine a case where they are not efficient enough)
Some languages: Scheme with its call/cc, Prolog with its backtracking features, are perhaps more adapted (than C99 is) to the needs of the OP.
After giving it some extra thought, it is not as simple as it initially appeared. There is one thing that prevents it from working - the code of functions is not context aware - there is no way of knowing the frame it was invoked in, and that has two implications:
1 - modifying the instruction pointer if not portable is easy enough, as every implementation defines a consistent place for it, it is usually the first thing on the stack, however modifying its value to skip the escape trap will also skip the code which restores the previous frame state, since that code is there, not in the current frame - it can't perform state restoration since it has no information of it, the remedy for that, if an extra check and jump are to be omitted is to duplicate the state restoring code in both locations, unfortunately, this can only be done in assembly
2 - the amount of instructions which need to be skipped is unknown too, and depends on which is the previous stack frame, depending on the number of locals that need destruction it will vary, it will not be a uniform value, the remedy for that would be to push both the error and success instruction pointers on the stack when the function is invoked, so it can restore one or the other depending on whether an error occurs or not. Unfortunately, that too can only be done in assembly.
Seems that such a scheme can only be implemented on level compiler, demanding its own calling convention, which pushes two return locations and inserts state restoration code at both. And the potential savings from this approach hardly merit the effort to write a compiler.
Here's the basic premise of my code:
while(norm_of_error > tol){
#pragma omp parallel for
for(i = 1; i <= N*N; i++){
//printf("thread id: %d\n",omp_get_thread_num());
:
int val = based on i
:
#pragma omp critical
x[i-1] = val;
}
#pragma omp barrier
iter++;
}
In short, I am solving Ax = b using the Jacobi iterative method. My problem is that, with the printf() statement uncommented, the norm_of_error tends to zero and the while loop ends. However, by simply commenting out the printf() statement, this doesn't happen. Can anyone give me a hint as to why the printf() statement has any impact? I'm guessing that the issue has to do with the call to omp_get_thread_num(), but I don't see why that would make any difference.
Edit: I changed the printf() statement to printf("hi\n"); and the code works. Comment that out, and the code doesn't work.
Code that works with a printf() statement present, but fails when it is removed, is usually a sign of some invalid operation affecting memory in the program somewhere (e.g. falling off the end of an array, dereferencing NULL, etc). The misbehaving code may be in some other section of the program entirely (e.g. not within the function that contains the printf() statement)
That is even more likely when the offending printf() statement is something obviously innocent, and without any side effects that can affect behaviour of other code (such as printf("Hi\n")).
The reason is that the presence of the extra printf() does actually affect layout of memory for the program as a whole. So the offending code (which may be in some completely unrelated part of the program) still overwrites memory, but the consequence changes (e.g. overwriting some data the program is permitted to change, rather than some area of memory that causes the operating system to terminate the program).
This is true whether or not the code is multithreaded.
Without complete code that illustrates the problem (i.e. a small sample that someone else can compile, build, and run to get the same symptom) it is not possible to be more specific.
You haven't posted your code so we can't know for sure, but this typically arises because you are trying to share data amongst threads without adequately indicating that the data is to be shared.
With the printf removed, your program is loading the data into a register, and when it needs the data again, it remembers the value in the register rather than fetching it from memory again, thus it doesn't see any changes your other threads may have made.
With the printf in place, your program doesn't hold the data in register -- maybe it can't afford to spend a register that way, or it can't determine that a function call is incapable of changing the data (sure, it's just printf, but it might not be special cased, and even if it is, the compiler is better at finding loopholes that might allow printf to change data than you are) -- so it rereads the data from memory after the call to printf, and thus sees whatever prior changes that have been made in other threads.
Another thing the printf could change is timing: I/O statements are pretty slow as compared to computation, and there is likely some amount of synchronization happening inside the I/O library; your print might be acting as a pseudo-barrier that is preventing a race condition from occurring.
Keep in mind that C and C++ are different languages.
The C FAQ has as section on strange problems:
comp.lang.c FAQ list · Question 16.5
Q: This program runs perfectly on one machine, but I get weird results on another. Stranger still, adding or removing a debugging printout changes the symptoms...
A: Lots of things could be going wrong; here are a few of the more common things to check:
uninitialized local variables [footnote] (see also question 7.1)
integer overflow, especially on 16-bit machines, especially of an intermediate result when doing things like a * b / c (see also question 3.14)
undefined evaluation order (see questions 3.1 through 3.4)
omitted declaration of external functions, especially those which return something other than int, or have ``narrow'' or variable arguments (see questions 1.25, 11.3, 14.2, and 15.1)
dereferenced null pointers (see section 5)
improper malloc/free use: assuming malloc'ed memory contains 0, assuming freed storage persists, freeing something twice, corrupting the malloc arena (see also questions 7.19 and 7.20)
pointer problems in general (see also questions 16.7 and 16.8)
mismatch between printf format and arguments, especially trying to print long ints using %d (see questions 12.7 and 12.9)
trying to allocate more memory than an unsigned int can count, especially on machines with limited memory (see also questions 7.16 and 19.23)
array bounds problems, especially of small, temporary buffers, perhaps used for constructing strings with sprintf [footnote] (see also questions 7.1, 12.21, and 19.28)
invalid assumptions about the mapping of typedefs, especially size_t (see question 7.15)
floating point problems (see questions 14.1 and 14.4a)
anything you thought was a clever exploitation of the way you believe code is generated for your specific system
Proper use of function prototypes can catch several of these problems; lint would catch several more. See also questions 16.3, 16.4, and 18.4.
This question isn't about the technical usage of restricted, more about the subjective usage. Although I might be mistaken as to how restricted technically works, in which case you should feel free to grill me for basing a question on a false premise.
Here are two examples of how I'm using restricted so far:
If I have a function that takes a pointer to a sequence of immutable chars, I don't say it's restricted, since other people are allowed to access the data via their own pointers at the same time as the function's executing, e.g. from another parallel thread. The data isn't being modified, so no problem.
However, if the function takes a pointer to a sequence of mutable chars that it might modify, I say it's restricted because the data absolutely should not be accessed in anyway from any pointer (bar the argument the function uses, obviously) during the execution of the function due to potentially inconsistent data. It also states the possibility of the data being modified, so the coder knows not to read stale data and that they should use a memory barrier when accessing or whatever...
I don't code much C, so I could easily be wrong about what I'm assuming here. Is this correct usage of restrict? Is it worth doing in this scenario?
I'm also assuming that once the restricted pointer is popped off the stack when the function returns, that the data can then freely be accessed via any other pointer again, and that the restriction only lasts as long as the restricted pointer. I know that this relies on the coder following the rules, since accessing a restricted data via an 'unofficial' pointer is UB.
Have I got all of this right?
EDIT:
I'd just like to make clear that I already know it does absolutely nothing to prevent the users from accessing data via multiple threads, and I also know that C89 has no knowledge of what 'threads' even are.
But given that any context where an argument can be modified via reference, it's clear that it mustn't be accessed as the function is running. This doesn't do anything to enforce thread safety, but it does clearly document that you modify the data through your own pointer during the execution of the function at your own risk.
Even if threading is taken completely out of the equation, you still allow for further optimizations in a scenario where it seems correct to me.
Even so, thanks for all your authoritative answers so far. Do I upvote all the answers that I liked, or just the one that I accept? What if more than one is accepted? Sorry, I'm new here, I'll look through the FAQ more thoroughly now...
restrict has nothing to do with thread safety. In fact, the existing C standards have nothing to say on the topic of threads at all; from the point of view of the spec, there is no such thing as a "thread".
restrict is a way to inform the compiler about aliasing. Pointers often make it hard for the compiler to generate efficient code, because the compiler cannot know at compile time whether two pointers actually refer to the same memory. Toy example:
void foo(int *x, int *y) {
*x = 5;
*y = 7;
printf("%d\n", *x);
}
When the compiler processes this function, it has no idea whether x and y refer to the same memory location. Therefore it does not know whether it will print 5 or 7, and it has to emit code to actually read *x before calling printf.
But if you declare x as int *restrict x, the compiler can prove that this function prints 5, so it can feed a compile-time constant to the printf call.
Many such optimizations become possible with restrict, especially when you are talking about operations on arrays.
But none of this has anything to do with threads. To get multi-treading applications right, you need proper synchronization primitives like mutexes, condition variables, and memory barriers... All of which are specific to your platform, and none of which have anything to do with restrict.
[edit]
To answer your question about using restrict as a form of documentation, I would say "no" to that, also.
You seem to be thinking that you should document when a variable can or cannot be concurrently accessed. But for shared data, the proper discipline is (almost always) to ensure that it is never concurrently accessed.
The relevant documentation for a variable is whether it is shared at all and which mutex protects it. Any code accessing that variable for any reason, even just to read it, needs to hold the mutex. The author should neither know nor care whether some other thread might or might not happen to be accessing the variable concurrently... Because that other thread will be obeying the same discipline, and the mutex guarantees there is no concurrent access.
This discipline is simple, it works, and it scales, which is why it is one of the dominant paradigms for sharing data between threads. (The other is message passing.) If you ever find yourself trying to reason "do I really need to lock the mutex this time?", you are almost certainly doing something wrong. It would be hard to overstate this point.
No, I don't think that this is a good dialect to provide any information about acces from different threads. It is meant as assertions about pointers that a particular peace of code gets for different pointers it handles. Threading is not part of the language, yet. Thread safe acces to data needs much more, restrict is not the right tool. volatile isn't a guarantee, which you sometimes see proposed as well.
mutexes or other lock structures
memory fences that ensure data integrity
atomic operations and types
The upcoming standard C1x is supposed to provide such constructs. C99 isn't.
The canonical example of restrict is memcpy() - which the manpage on OS X 10.6 gives the prototype as:
void* memcpy(void *restrict s1, const void *restrict s2, size_t n);
The source and destination regions in memcpy are not permitted to overlap; therefore by labelling them as restrict this restriction is enforced - the compiler can know that no part of the source array aliases with the destination; can it can do things like read a large chunk of the source and then write it into the destination.
Essentially restrict is about assisting compiler obtimizations by tagging pointers as not aliasing - in and of itself it doeen't help with thread safety - it doesn't automatically cause the object pointed to be to locked while the function is called.
See How to use the restrict qualified in C and the wikipedia article on restrict for a more lengthy discussion.
restrict is a hint to the compiler that the buffer accessed via a pointer is not aliased via another pointer in scope. So if you have a function like:
foo(char *restrict datai, char *restrict dataj)
{
// we've "promised" the compiler that it should not worry about overlap between
// datai and dataj buffers, this gives the compiler the opportunity to generate
// "better" code, potentially mitigating load-store issues, amongst other things
}
To not use restrict is not enough to provide guarded access in a multi-threaded application though. If you have a shared buffer simultaneously accessed by multiple threads via char * parameters in a read/write way you would potentially need to use some kind of lock/mutex etc - the absence of restrict does not imply thread safety.
Hope this helps.
I need to write my own memory allocation functions for the GMP library, since the default functions call abort() and leave no way I can think of to restore program flow after that occurs (I have calls to mpz_init all over the place, and how to handle the failure changes based upon what happened around that call). However, the documentation requires that the value the function returns to not be NULL.
Is there at least one range of addresses that can always be guaranteed to be invalid? It would be useful to know them all, so I could use different addresses for different error codes, or possibly even different ranges for different families of errors.
If the default memory allocation functions abort(), and GMP's code can't deal with a NULL, then GMP is likely not prepared to deal with the possibility of memory allocation failures at all. If you return a deliberately invalid address, GMP's probably going to try to dereference it, and promptly crash, which is just as bad as calling abort(). Worse, even, because the stacktrace won't point at what's really causing the problem.
As such, if you're going to return at all, you must return a valid pointer, one which isn't being used by anything else.
Now, one slightly evil option would be to use setjmp() and longjmp() to exit the GMP routines. However, this will leave GMP in an unpredictable state - you should assume that you can never call a GMP routine again after this point. It will also likely result in memory leaks... but that's probably the least of your concerns at this point.
Another option is to have a reserved pool in the system malloc - that is, at application startup:
emergencyMemory = malloc(bignumber);
Now if malloc() fails, you do free(emergencyMemory), and, hopefully, you have enough room to recover. Keep in mind that this only gives you a finite amount of headroom - you have to hope GMP will return to your code (and that code will check and see that the emergency pool has been used) before you truly run out of memory.
You can, of course, also use these two methods in combination - first use the reserved pool and try to recover, and if that fails, longjmp() out, display an error message (if you can), and terminate gracefully.
No, there isn't a portable range of invalid pointer values.
You could use platform-specific definitions, or you could use the addresses of some global objects:
const void *const error_out_of_bounds = &error_out_of_bounds;
const void *const error_no_sprockets = &error_no_sprockets;
[Edit: sorry, missed that you were hoping to return these values to a library. As bdonlan says, you can't do that. Even if you find some "invalid" values, the library won't be expecting them. It is a requirement that your function must return a valid value, or abort.]
You could do something like this in globals:
void (*error_handler)(void*);
void *error_data;
Then in your code:
error_handler = some_handler;
error_data = &some_data;
mpz_init(something);
In your allocator:
if (allocated_memory_ok) return the_memory;
error_handler(error_data);
abort();
Setting up the error handler and data before calling mzp_init might be somewhat tedious, but depending how different the behaviour is in different cases, you might be able to write some function or macro to deal with it.
What you can't do, though, is recover and carry on running if the GMP library isn't designed to cope after an allocation fails. You're at the mercy of your tools in that respect - if the library call doesn't return on error, then who knows what broken state its internals will be left in.
But that's a fully general view, whereas GMP is open source. You can find out what actually happens in mpz_init, at least for a particular release of GMP. There might be some way to ensure in advance that your allocator has enough memory to satisfy the request(s), or there might be some way to wriggle out without doing too much damage (like bdonlon says, a longjmp).
Since nobody has provided the correct answer, the set of non-NULL memory addresses you can safely use as error values is the same as the set of addresses you create for this purpose. Simply declare a static const char (or global const char if you need it to be globally visible) array whose size N is the number of error codes you need, and use pointers to the N elements of this array as the N error values.
If your pointer type is not char * but something else, you may need to use an object of that type instead of a char array, since converting these char pointers into another pointer type is not guaranteed to work.
Only garanteed on current main stream operating systems (with enabled virtual memory) and CPU architectures:
-1L (means all bits on in a value large enough for a pointer)
This is used by a lot of libraries to mark pointers which are freed. With this you can find out easily if the error cames from using a NULL pointer or a hanging reference.
Works on HP-UX, Windows, Solaris, AIX, Linux, Free-Net-OpenBSD and with i386, amd64, ia64, parisc, sparc and powerpc.
Think this works enough. Don't see any reason for more then this two values (0,-1)
If you only return e.g. 16-bit or 32-bit aligned pointers, an uneven pointer-address (LSB equal to 1) will be at least "mysterious", and would create an opportunity for using my all-time favorite bogus-value 0xDEADBEEF (for 32-bit pointers) or 0xDEADBEEFBADF00D (for 64-bit pointers).
There are several ranges you can use, they are operating system and architecture specific.
Typically most platforms will reserve the first page (usually 4K bytes in length), to catch dereferencing of null pointers (plus room for a slight offset).
You can also point to the reserved operating system pages, on Linux these occupy the region from 0xc0000000 to 0xffffffff (on a 32 bit system). From userspace you won't have necessary privileges to access this region.
Another option (if you want to allocate several such values, is to allocate a page without read or write permissions using mmap or equivalent, and use offsets into this page for each distinct error value.
The simplest solution, is just to use either values immediately negative to 0, (-1, -2, etc.), or immediately positive (1, 2, ...). You can be very certain these addresses are on inaccessible pages.
A possibility is to take C library addresses that are guaranteed to exist and that thus will never be returned by malloc or similar. To be most portable this should be object pointers and not function pointers, but casting ((void*)main) would probably be ok on most architectures. One data pointer that comes to my mind is environ, but which is POSIX, or stdin etc which are not guaranteed to be "real" variables.
To use this you could just use the following:
extern char** environ; /* guaranteed to exist in POSIX */
#define DEADBEAF ((void*)&environ)