0

I could be totally off in my understanding of the use of RAII class to ensure resources are released, but the following example appears to show that a local object of a RAII class need not be able to release its resource when the program crashes:

// Compiled via command:
//    /c/opt/mingw64/bin/x86_64-w64-mingw32-g++.exe -D_WIN64 -Wall -Wextra -Werror -std=c++11 -O3 -static-libgcc -static-libstdc++ local_raii.cc -o local_raii.exe
#include <fstream>
#include <iostream>
#include <thread>
#include <mutex>

class some_raii
{
    public:
        some_raii( int i,  const char *message ) : which_one(i)
        {
            std::unique_lock<std::mutex> mu_lock( mu );
            of() << "Started "
                 << which_one
                 << " " 
                 << message
                 << "\n";
            of().flush();
        }
       ~some_raii()
       {
            std::unique_lock<std::mutex> mu_lock( mu );
            of() << "Done with "
                 << which_one
                 << "\n";
            of().flush();
       }

       static std::ofstream& of();
       static std::mutex     mu;

       int which_one{0};
};

std::ofstream& some_raii::of()
{
    static std::ofstream a_of( "output.txt" );
    return a_of;
}

std::mutex   some_raii::mu;

some_raii  globals_destructor_is_called( 100,  "" );

int main()
{
    some_raii locals_destructor_is_NOT_called( 201,  "destructor will not be called -- where's the resource release via RAII?" );

    {
        some_raii fhoo( 301,  "" );
    }

    std::chrono::milliseconds interval( 500 );

    std::cout << "press CTRL-C to terminate this program ...\n"
              << std::flush;
    while(1)
    {
        static int i = 400;
        some_raii fgoo( i++,  "where's the resource release via RAII for the _last_ one?" );
        std::this_thread::sleep_for( interval );
    };

    std::cout << "This line will not be seen\n" << std::flush;

    return 0;
}

As can be seen from the output from one run of above program:

Started 100
Started 201 destructor will not be called -- where's the resource release via RAII?
Started 301
Done with 301
Started 400 where's the resource release via RAII for the _last_ one?
Done with 400
Started 401 where's the resource release via RAII for the _last_ one?
Done with 401
Started 402 where's the resource release via RAII for the _last_ one?
Done with 100

the destructors of a local RAII object need not be called when the program crashes. So if this RAII object opened some hardware in its constructor then that hardware would not be closed (since its destructor is never executed).

Questions: Does the C++11 standard provide some mechanism to allow use of local RAII objects to manage a resource such as opening and closing some hardware? If it doesn't then, since Bjarne Stroustrup promotes the use the RAII class, why is he OK with the behavior illustrated here?

Mankarse
  • 39,818
  • 11
  • 97
  • 141
user1823664
  • 1,071
  • 9
  • 16
  • 1
    The fact that the program is getting terminated by some outside force indicates that there exists an outside force that can control the program and its environment. If this outside force is going to forcefully terminate the program, it should accept the consequences of doing so (like the possibility that the program will not completely do its job). Usually, the outside force is the operating system, and usually the operating system will ensure that any resources allocated by the process are released when the process is exited. – Mankarse Jun 11 '14 at 04:49
  • 4
    *No* programming language can by itself ensure safety in the presence of external forces that are out of the language's control (such as power-outages, operating-system interrupts, hardware faults, etc.), these sorts of problems must be handled by a different layer. – Mankarse Jun 11 '14 at 04:52
  • 1
    If you are only interested in fixing the problem in this localised example, you can explicitly trap the `SIGINT` signal (with [std::signal](http://en.cppreference.com/w/cpp/utility/program/signal)), and write your program so that it exits cleanly when that signal is received. – Mankarse Jun 11 '14 at 04:57
  • 1
    To clarify: whatever outside force has the power to forcefully exit a C++ program will presumably also have the power to release any resources allocated by that process. The C++ abstract machine ceases to exist at program termination. Excluding outside forces and bugs, a C++ program will correctly release all properly managed resources before exiting. Without RAII, it is likely that a program will be unnecessarily polluted with `try`, `catch`, duplicate resource-release blocks and will contain bugs as a result of the overly complicated code. – Mankarse Jun 11 '14 at 05:01
  • RAII is promoted because it simplifies code and so reduces development effort and reduces the number of bugs likely to be present. – Mankarse Jun 11 '14 at 05:08
  • Regarding signal handling, you might wanna check out Beej's introduction: http://beej.us/guide/bgipc/output/html/multipage/signals.html – DanielKO Jun 11 '14 at 08:11

0 Answers0