C++ [[noreturn]] function call and destructors

172 Views Asked by At

I have some C++ code in which I must be sure that a specific destructor is called before exiting and I was wondering whether or not it was called before a [[noreturn]] function.

So I wrote this simple dummy example

#include <cstdio>
#include <cstdlib>
class A {
        char *i;
public:
        A() : i{new char[4]} {}
        ~A() { delete[] i; }
        void hello() { puts(i); }
};

int func()
{
        A b;
        exit(1);
        b.hello(); // Not reached
}

I compiled with g++ /tmp/l.cc -S -O0 and I got this assembly

    .file   "l.cc"
    .text
    .section    .text._ZN1AC2Ev,"axG",@progbits,_ZN1AC5Ev,comdat
    .align 2
    .weak   _ZN1AC2Ev
    .type   _ZN1AC2Ev, @function
_ZN1AC2Ev:
.LFB18:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movq    %rdi, -8(%rbp)
    movl    $4, %edi
    call    _Znam
    movq    %rax, %rdx
    movq    -8(%rbp), %rax
    movq    %rdx, (%rax)
    nop
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE18:
    .size   _ZN1AC2Ev, .-_ZN1AC2Ev
    .weak   _ZN1AC1Ev
    .set    _ZN1AC1Ev,_ZN1AC2Ev
    .text
    .globl  func
    .type   func, @function
func:
.LFB24:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    leaq    -8(%rbp), %rax
    movq    %rax, %rdi
    call    _ZN1AC1Ev
    movl    $1, %edi
    call    exit
    .cfi_endproc
.LFE24:
    .size   func, .-func
    .ident  "GCC: (GNU) 12.2.1 20221121 (Red Hat 12.2.1-4)"
    .section    .note.GNU-stack,"",@progbits

There was clearly no call to the destructor.

In this stupid case it doesn't matter much, but what if I had to close a file before exiting?

1

There are 1 best solutions below

0
On

Apart from the fact that terminating a program with exit() is generally considered bad practice, you could try the following:

int func()
{
    {
        A b;
        /* ... */
    } // Leaving scope => destructing b
    exit(1);
}

PS: Assuming that you aren't writing a driver, most kernels (including Microsoft Windows NT, Unix (e.g. BSD), XNU (macOS) and Linux) automatically deallocate any allocated memory as the program exits.