When I call a trampoline nested function inside another nested function, the trampoline nested function doesn't have access to the trampoline variables, in this case the float, r.
typedef void (*callback)();
callback Wrapper(float r) {
auto void foo();
void foo() {
// do something with r.
}
return &foo;
}
int main(void)
{
callback c = Wrapper(0.1);
auto void foo2();
void foo2() {
c(); // doesn't work unless i don't use r in foo (Segmentation fault (core dumped))
}
foo2();
c(); // works fine.
return 0;
}
From gcc documentation nested functions:
If you try to call the nested function through its address after the containing function exits, all hell breaks loose.
The function void foo is defined inside function Wrapper and the address to the function foo is returned from Wrapper. Then you call the function after the function Wrapper exits. As documentation states your code makes "all hell break loose".
Think of a nested function as a variable allocated on stack. When the function returns, the nested function stops existing.
the trampoline nested function can't access to the trampoline variables, in this case the float r.
The variable r has scope only within Wrapper function. Once Wrapper exits, the variable r stops existing.
auto void foo();
auto void foo2();
That's odd. There's no need to write that. Just write the function - it's like auto by default anyway.
You cannot use c() once Wrapper() has finished, because it is out of scope. Think of it as if that function existed only while Wrapper() was being executed (even if you know that it's code is still somewhere, you cannot execute it for the reasons explained below, if it is not from the inside of the function that contains it) You call Wrapper() in the beginning of main(), and Wrapper() returns a pointer to a function that is local to Wrapper(). Well, that pointer is a fake pointer because the function has ceased to exist as soon as the program returned from Wrapper. This is like returning a pointer to a local variable.
I should say Undefined Behaviour, but as we are talking about a GCC extension, that term is out of scope also, so what can I say then? (As I have seen from the other answer by KamilCuk, GNU uses the term all hell breaks loose, which sounds perfect for me)
The implementation of nested functions means using displays (arrays of pointers to the closest active call records of all the nested functions out of this one, this is done in other languages, like Pascal, Ada or Modula-2) to access the scoped identifiers in outer functions, like you do, when you access the float r from c(), but later, when Wrapper is not being executed, no display exists of the local variables in Wrapper() and the call to c() is in error because the access to the value 1.0 has gone long ago.
For all purposes, your trick to try to call c() out of scope (outside of Wrapper()) is illegal, and I don't know why can you require this, but you are wrong if you thought you can maintain a local resource (like the parameter r in Wrapper, after the call to the function that used it has return)
I suggest you to have a look to the array of nested function pointers and how the compiler access to variables on the outer function through the display, by looking at the assembly code of the nested functions (you can nest indefinitely, and at each level of nesting you add one more pointer to the vector) In standard C there are no displays, because all the functions are defined at top level.
Related
I have two functions that call each other, inside of another function:
int main(){
void aaa();
void b(){
aaa();
}
void aaa(){
b();
}
aaa();
}
(Yes, this example would be stuck in an infinite loop or cause a stack overflow)
The compiler throws the error: static declaration of 'aaa' follows non-static declaration
If I move the function declarations outside of the other function, it works (but I can't do that because those functions need to have access to main's local variables)
Is it possible to make this work?
C does not support nested functions, nor closures.
One solution for your actual problem is to define the shared state (the local variables of main you mentioned, in this case) as struct, then have variable of this struct type, and pass it as pointer to the functions that use it.
You don't show the local variable code in your question, so I'm not writing and arbitrary example. Please edit the question with more code, if you want an example.
Another solution is to just use global (preferably static) variables, used both from other functions and main. I mean, since main isn't a normal function (can't be called recursively by standard, for example), its local variables end up being unique objects anyway, so this is just a matter of scope and visibility, with little to no funcional difference.
I know that C does not support nested functions and it's only a gcc extension. But even so, this behavior is strange.
It seems like the nested functions can be called only once; the second calling causes SIGSEV, and sometimes SIGILL. I want nested functions for structures like stack. On stack, I would be able to define functions like pop, push, etc., which I will assign with nested functions, which will call normal functions with reference, which I will get. This function is like a constructor, or initializer. But this code is enough to simulate my problem.
When generate function assigns innerFunction into struct, second calling causes an error. If the assignment is to test function, second calling is ok.
Where is the problem, please? In gcc documentation, it says that as long as you have inner function address, you can access this function and nested function has access into all variables defined above.
typedef struct A A;
struct A {
void (*foo)();
};
void test() {
printf("test\n");
}
void generate(A* a) {
void innerTest(){
test();
}
a->foo = &innerTest;
}
int main() {
A a;
generate(&a);
a.foo();
a.foo();
};
Do not allow pointers to inner functions to escape the stack frame they were created on. This yields undefined behavior.
The code generated places a trampoline on the stack. With the particular construct you have created, the trampoline got overwritten with your first call to the function so it failed at the second call to the function.
I personally am annoyed that it invokes that behavior without a closure to care about, but that's what it does. Oh wait I get it. your example works because in pairing it down this far you accidentally reduced it to working code (see acorngal's comment). Your real code accesses the pointer to structure labelled a and so does force a closure and therefore a trampoline. You cannot do this stunt in C; when doing OO programming you must pass the equivalent to the this pointer yourself.
I'm trying to achive a function to be called only one time. But I want to save the if (firstTime) check.
What I'm thinking about was:
while (1)
{
foo();
}
foo()
{
static int test = 1, srand (test);
test++;
}
But I couldn't find anything in the standard what is covering this.
So I'm not sure about, this is undefined. And if not so, will srand be invoked as expected? If not so, is it (as the main question is) even possible to invoke functioncalls on translationtime (what would more be, behave as if), as I'm doing here?
As an option to a first time flag, you could use a pointer to function that is initially set to the first time function, which in turn would set the pointer to function to the actual function. There's a level of indirection, but it eliminates a conditional branch.
A more general version of this idea is to use the pointer to function as a "state machine", where each function "advances" (sets) the pointer to the next state (the next function as part of a series of functions). This can be handy for event or interrupt driven code. I've used this method for device drivers and embedded code.
Your idea is probably that using a function call as an initializer for a static variable would call that function only once a program startup.
No, this is not possible in C, only constants are allowed in that context. In C++ this would be possible, and the compiler applies some secret wisdom to know in which order such initializations are effected.
I've been running into a minor problem with regards to seeing people, currently helping a teacher out through grading, and seeing people declaring functions within the scope of main, instead of within the global scope, as I was taught to do, I understand that this still works in itself, but I am kind of confused as to what happens with these functions, should a function be called, that was declared in main, in another function that is not declared inside said main, would this in itself work, and if it does, why. Isn't the function within only the scope of main, and as such shouldn't it remain local to it, or dies C just allocate the space in memory for the functions call at a global scope from the time it is declared, and subsequently defined? Know I was rambling a bit on this, trying to cover all possible questions within this scope.
Sample of what I mean.
int main(){
void foo(int bar);
int boo;
foo(boo);
return 0;
}
void foo(int bar){
...
}
The point that I was trying to stress is that the functions are usable due to the fact that they are related, through main if that makes any sense, but should a function be declared on the global scope such as
#include <stdio.h>
void roo(void);
int main(){} //Holds the same syntax as above with the function declared within it.
//Function foo is same as defined prior.
//Then function roo is defined but uses foo within itself.
void roo(void){
int boo;
foo(boo);
...
}
Shouldn't the codes being compounded, not work fully since the function roo technically has no way to access the function within the scope of main?
edit --
I somewhat saw a point that main would be, with the current lack of multiple functions to be called, would still be at the time used to call function roo, but should this contain multiple functions then wouldn't it be kind of weird or not syntax legal to call up foo from within roo, if it were scaled about 6 functions outside from main.
Declarations are needed for type checking and linking. They exist at compile-time only - they don't actually create an "object" (such as a function body) that exists in any way in the compiled program - all they do is put a name on it, so that other parts of the source can refer to that object without having it immediately to hand. Definitions create objects, but declarations create names.
Going through your example:
void roo(void); // roo becomes visible
int main(){ // main is defined, AND becomes visible
void foo(int bar); // foo becomes visible
foo(6);
roo();
} // foo is no longer visible
void foo(int bar){ /**/ } // foo is defined AND becomes visible
void roo(void){ // roo is defined, but was already visible
foo(6); // so this has no effect on other functions
}
roo can be called from any code in the program below where it was declared, because its name has been put in global scope and is visible from all nested scopes. The following code is aware that somewhere (no idea where), a function called roo exists and is available for use.
Moving down into main, a new scope is opened, and foo made visible within it. main uses this information to call to foo. It uses the information in the global scope to call to roo. The scope closes with the end of main and foo ceases to be visible to the following code; it is not aware that any such function exists.
foo is the simultaneously defined and declared in the global scope. All following code is aware that a function called foo is available for use.
Similarly for roo.
The only places anything is given space in memory are at the three points of definition. None of the declarations cause anything to be allocated, statically or otherwise. All they do is make the code aware of an allocation elsewhere (to be resolved by the linker).
So to (what I think was) the original point of confusion: main calls roo, and roo calls foo, but the declaration of foo in main is not visible to roo. (It sounds like you're confusing static and dynamic semantics: C has static scope only.)
This isn't a problem, because main doesn't know the content of roo, and doesn't need to know its content (some compilers perform inlining; we don't care about that). Control leaves the body code of main and goes to a different point in the program. The body of a function is a black box to every other function; what happens within the code of roo is completely unknown to every other function. roo also doesn't inherit the scope of main, so it has no knowledge of anything that was declared at that time (globally, locally, or otherwise) - it uses the scope opened and closed by its own body further down for name lookups. In that scope, foo has already been declared globally (it inherits the global scope at a separate fixed point on the page), so roo can see foo of its own accord.
Each function exists in one (and exactly one) place. All declarations do is make that place visible to the code that uses it. Code that doesn't use it, doesn't need to be able to see it. main can't see the nested call to foo, so any declaration at that point isn't relevant to it.
I was trying to understand the difference between closures and function pointers, and I came across this answer in SO
What I don't understand is this code
BOOL (*lessThanTest)(int);
int lessThan = 100;
lessThanTest = &LessThan;
BOOL LessThan(int i) {
return i < lessThan; // compile error - lessThan is not in scope
}
Why there is a compile error consideringn that lessThan is a global variable, it can be accessed from within LessThan function, did I miss something?
EDIT
This is not my code, it's taken from an answer in SO Function pointers, Closures, and Lambda
Closures take all the variables in their lexical scope along for the ride, possibly extending their lifetimes. Function pointers don't -- if the variables referenced inside their code disappear, they're hosed.
The code example you've given is a little bit confusing. I believe that it's meant to be inside of a function, meaning that lessThan is a local variable. If that scope is exited, but the function pointer still exists, then its code would have a reference to a non-existent variable -- lessThan.
You missed a paragraph in that answer:
But, now I have to pass the 2 arguments when I evaluate it. If I wished to pass this function pointer to another function where lessThan was not in scope, I would either have to manually keep it alive by passing it to each function in the chain, or by promoting it to a global.
In what you posted, int lessThan is not meant at global scope, it should be assumed to be in a function somewhere.
Well, no, if lessThan is global, it shouldn't produce compile error, though you can hardly tell by this fragment what is meant to be where. lessThanTest=&LessThan; is definitely from some local scope, for instance.
This code has some problems:
You declare lessThanTest as an uninitialized function pointer
You can't assign something to it later under global scope
You're using LessThan before declaring it.