Search code examples
c++g++visual-studio-2022

Is the std::atexit function does not work in the MSVC compiler?


I want to run a function with parameters and a return value of void when exiting the program. I use the following code to implement it:

#include<bits/stdc++.h>
#include<windows.h>
using namespace std;
void Exit(string s){
    ofstream ofs;
    ofs.open("E:\\code\\file.txt",ios::out);
    ofs << s << endl;
    ofs.close();
}
int main(){
    auto callback = std::bind(Exit, "test");
    static std::function<void()> atExitCallback = callback;
    atexit([] { atExitCallback(); });
    while(1){
        cout << "running..." << endl;
        Sleep(500);
    }
    system("pause");
    return 0;
}

When the program exits, it will create a file in the path I specified and write the specified content. When I use g++ to generate executable programs, the program is able to create files when exiting. But when I use MSVC to generate executable programs, the program is not able to create files when exiting. I think the std::atexit function is not working in the MSVC compiler. My g++ version is 11.2.0,MSVC version is 19.37.32825

Is there a way to make my code work in the MSVC compiler, that is, to get the same result as the g++ compiler when the program exits


Solution

  • From the doc: https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/atexit?view=msvc-170,

    The atexit function is passed the address of a function func to be called when the program terminates normally.

    To trigger a function when the terminal exits, use SetConsoleCtrlHandler instead of atexit.

    #include <iostream>
    #include <fstream>
    #include <windows.h>
    #include <functional>
    
    void Exit(std::string s) {
        std::ofstream ofs;
        ofs.open("E:\\code\\file.txt", std::ios::out);
        ofs << s << std::endl;
        ofs.close();
    }
    
    std::function<void()> atExitCallback;
    
    BOOL WINAPI ConsoleHandler(DWORD signal) {
        if (signal == CTRL_C_EVENT || signal == CTRL_CLOSE_EVENT || signal == CTRL_BREAK_EVENT) {
            if (atExitCallback) {
                atExitCallback();
                exit(1);
            }
            return TRUE;
        }
        return FALSE;
    }
    
    int main() {
        auto callback = std::bind(Exit, "test");
        atExitCallback = callback;
    
       
        if (!SetConsoleCtrlHandler(ConsoleHandler, TRUE)) {
            std::cerr << "Error: Could not set control handler." << std::endl;
            return 1;
        }
    
        while (true) {
            std::cout << "running..." << std::endl;
            Sleep(500);
        }
    
        return 0;
    }