-1

I want to trigger a function with parameters just before exiting the program (exit by "return" in the main or by closing the console). My function will print the values of certain variables in a file.

Using the function "atexit" not help me because the pointer to the function is without parameters.

Thanks

P.S. My major problem is when I interrupt the execution of my program by closing the console, I want to get tthe value of some variables at that moment :

ostream out("myFile.txt");
int **S;
int n;
...
void fn(void)
{
  out << "S = " << endl;
  for(int i=0; i<n; i++)
  {
      for(int j=0; j<n; j++)
      {
          out << S[i][j] << " " << endl;
      }
      out << endl;
  }
}
...
int main()
{
   atexit(fn); // not working if i interrupt the execution
   ... // a big loop of code
   return 0;
}

I think it will be easy to understand mu issue with this example.

Regards

  • 1
    Maybe it helps: https://stackoverflow.com/questions/8053000/passing-values-to-atexit/8053261#8053261 – Bartosz Charuza Aug 23 '22 at 23:23
  • 4
    This is probably too obvious to be a useful answer but: why not add a call to the function at the bottom of main()? – Jeremy Friesner Aug 23 '22 at 23:28
  • Make a "no parameter" function that calls your function that takes parameters, then pass *that* function to `atexit`. – Mark Tolonen Aug 23 '22 at 23:30
  • 1
    What is the real problem you're trying to solve? No, not the one about calling a function "just before exiting the program", but the problem to which you believe the solution is to call a function just before existing the program, so that's what you're asking about. – Sam Varshavchik Aug 23 '22 at 23:31
  • I will try all propositions, thanks to all of you. – Amine Badr Aug 24 '22 at 00:17
  • @BartoszCharuza the proposed solution don't work if I interrupt the execution. – Amine Badr Aug 24 '22 at 10:55
  • @JeremyFriesner It will be simple if I will just wait until the end of the execution, but if i will interrupt it before finishing, it will never be executed – Amine Badr Aug 24 '22 at 10:57
  • @MarkTolonen I tried but without success – Amine Badr Aug 24 '22 at 10:58
  • @SamVarshavchik I'm open to any suggestion to resolve this issue. – Amine Badr Aug 24 '22 at 11:00
  • 1
    Sure, but you need to explain what the issue is. Please explain what the issue is; no, not the one about calling a function before exiting the program, that's just what you think is the solution to the real problem, which you haven't explained. Can you explain what the real problem is. – Sam Varshavchik Aug 24 '22 at 11:45
  • 1
    @AmineBadr it sounds like what you really want to do is handle the console-closing event so that your program can exit gracefully in response (including calling your function) rather than just being terminated. See this question for some help with that: https://stackoverflow.com/questions/9369120/c-how-do-i-check-if-my-window-is-about-to-close/9369261#9369261 – Jeremy Friesner Aug 24 '22 at 14:21

2 Answers2

0

One option that comes to mind is to use lambdas for this (https://en.cppreference.com/w/cpp/language/lambda) in conjunction with atexit. atexit takes a function pointer to a function with no arguments. What we can do here is wrap the function call we want to happen in a lambda. Let me explain what I mean.

First we have to make sure we're on the same page with lambdas. Basically, you can think of them as unnamed functions. An important thing to note is that with lambdas in C++, we can capture variables in the current context, which we call our captures. This just means when the lambda is called, it will be able to reference these variables and the values they hold at the time of capture. With that in mind, consider this example:

int x = 1;
auto myLambda = [x](){ return x; };

We've "captured" the value of x by putting it inside of those square brackets. Now, when myLambda is run (which we do with the code myLambda()) the code in the curly braces is executed and we get the value of x. But what's neat is that this works outside the context x was defined.

With all this in mind, what I recommend you do is write a lambda which captures the variables you want to use as parameters in the function you want to call. Then, within the lambda, call your function, passing those values as the parameters. This essentially creates what we can call a "wrapper function" which has zero arguments but calls a function which has arguments. Now you can pass this lambda into noexit. That lambda might look something like:

auto yourLambda = [parameter1, parameter2](){ return someFunc(parameter1, parameter2); };

Naturally, replace the parameters with your variable names and someFunc with your function name.

Hope this helps!

maxmm
  • 91
  • 3
  • I fear `atexit` will be too stupid to accept a lambda with captures. The signature of `atexit-handler` is blurry, but I have no reason to believe that it won't merely be a function pointer. – user4581301 Aug 23 '22 at 23:39
  • Not blurry at all in the C++ Standard: According to [**cstdlib.syn**](http://eel.is/c++draft/cstdlib.syn#header:%3ccstdlib%3e) we get `extern "C++" using atexit-handler = void();` and `int atexit(atexit-handler* func) noexcept;` Dumb-stupid function pointer that can't hold a lambda with captures. – user4581301 Aug 23 '22 at 23:49
  • I will try it, it's my first time to see the lambdas, thanks – Amine Badr Aug 24 '22 at 00:15
  • @AmineBadr don't spend too much time on the attempt. I doesn't work. Function pointers can't hold state the way a lambda can, and the lambda needs to be convertible into a function pointer in order to be accepted by `atexit`. – user4581301 Aug 24 '22 at 00:35
  • @user4581301 Thanks for the reply, i will search another solution – Amine Badr Aug 24 '22 at 10:41
0

Thanks to all of you, the answer proposed by @JeremyFriesner gives me the right thing to do, my code will be like :

#include <iosrteam>
#include <Windows.h>
...
int **S;
int n;
ofstream out("MyFile.txt");
BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
    switch (CEvent)
    {
        case CTRL_C_EVENT:
        case CTRL_BREAK_EVENT:
        case CTRL_CLOSE_EVENT:
        case CTRL_LOGOFF_EVENT:
        case CTRL_SHUTDOWN_EVENT:
            out << "S = " << endl;
            for(int i=0; i<n; i++)
            {
                for(int j=0; j<n; j++)
                {
                    out << S[i][j] << " " << endl;
                }
                out << endl;
            }
    }
    return TRUE;
}
...
int main()
{
    if (SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE) == FALSE)
    {
        cout << "The handler is not going to work." << endl;
    }
    ... // a big loop of code
    return 0;
}

This will allow me to save my variables to my file just before closing the console. The unique inconvenient is the time we have to save my data is only 5 seconds if we interrupt the console by clicking the "x" and 30 seconds otherwise. I think the 5 seconds will be sufficient for the small data but otherwise, it will be lost.

Thanks a lot for everyone try to help me with this issue.