2

I have the function that returns a nested function:

typedef int (*fp)();

fp makeCounter(){
  static int i=0;
  fp counter(){
    return i++;
  }
  return counter;
}

int main(){
  fp ctr=makeCounter();
  printf("%d\n",ctr());
}

makeCounter returns a function pointer to a locally defined nested function, which to me looks like an undefined behavior.

However I did not find definitive confirmation on this. On the GNU website, it says:

If you try to call the nested function through its address after the containing function exits, all hell breaks loose. If you try to call it after a containing scope level exits, and if it refers to some of the variables that are no longer in scope, you may be lucky, but it’s not wise to take the risk. If, however, the nested function does not refer to anything that has gone out of scope, you should be safe.

I am not very sold on the wording breaks loose or should be safe. Is there a definitive confirmation of reference on this topic?

If this is an undefined behavior, is there anyway to get around this? I know usually we define a local variable as static to allow global access, can we do something similar in this case?

EDIT I understand it is a GNU extension. The question is as above.

SwiftMango
  • 15,092
  • 13
  • 71
  • 136
  • 4
    Don't use nested functions in C — period. They're a non-standard GCC extension, and therefore not portable to other compilers. Your quote says that invoking the function after `makeCounter()` has exited triggers undefined behaviour and "all hell breaks loose". Don't do it. You're told not to. Regardless of what happens when you try it, you're not guaranteed to be successful. – Jonathan Leffler Nov 24 '17 at 02:18
  • 4
    @JonathanLeffler: Extensions were created to be used. Every extension was conceived of to solve a problem somebody had, and labor was put into implementing them because they have value. Telling people not to use extensions in programs they want to be portable is sensible. Telling people not to use extensions “period” is as absurd as telling people never to use Java or Python because they are not standard C. Extensions are tools and should be used when they suit the designer’s purpose. – Eric Postpischil Nov 24 '17 at 02:26
  • 2
    I have to work with archaic compilers like MSVC that don’t understand C99, let alone GNU extensions. If your work allows you to use extensions, great. For many people, that isn’t a worthwhile option. I’d have to write at least twice as much code (one lot using the extension, one lot working with I extended compilers), and face twice the testing, and … it is not worth my time to try such extensions. – Jonathan Leffler Nov 24 '17 at 02:27
  • @JonathanLeffler I am targetting gcc and clang, in which I use a macro to distinguish. For clang, I use its feature block. I don’t think portability is my concern here. But thanks for your concern – SwiftMango Nov 24 '17 at 02:33
  • 2
    If you only need to work with GCC and Clang, you’re lucky. You may use whatever extensions you wish. But you still shouldn’t abuse them. The manual you quote says you are abusing the feature. Rest assured that abuse will catch up with you sooner or later. Don’t risk it unless you’re very confident in your QA suite. – Jonathan Leffler Nov 24 '17 at 02:38
  • Why not just declare `i` and `counter` at file scope with `static`? That will achieve the same thing in a well defined and portable manner. Also, `counter` should return type `int`, not `fp`. – dbush Nov 24 '17 at 03:17
  • @dbush I think static nested function is not allowed, as written in the bottom of that page – SwiftMango Nov 24 '17 at 03:19
  • @texasbruce I mean not using a nested function at all. Define `i` and `counter` at the top level, and mark them as `static` so they aren't visible in other source files without a pointer. – dbush Nov 24 '17 at 03:22
  • take a look at [implementation-of-nested-functions](https://stackoverflow.com/questions/8179521/) – pynexj Nov 24 '17 at 03:23

0 Answers0