C++中的[[noreturn]]函数调用和析构函数

huangapple go评论67阅读模式
英文:

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

问题

这里是代码部分的翻译:

我有一些C++代码,其中我必须确保在退出之前调用特定的析构函数,我想知道在调用[[noreturn]]函数之前是否已经调用了它。

所以我写了这个简单的示例
```cpp
#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
}

我使用g++ /tmp/l.cc -S -O0编译后,得到了以下汇编代码

	.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

显然没有调用析构函数。

在这种愚蠢的情况下,这不太重要,但如果我需要在退出之前关闭一个文件呢?


<details>
<summary>英文:</summary>

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
```cpp
#include &lt;cstdio&gt;
#include &lt;cstdlib&gt;
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	&quot;l.cc&quot;
	.text
	.section	.text._ZN1AC2Ev,&quot;axG&quot;,@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	&quot;GCC: (GNU) 12.2.1 20221121 (Red Hat 12.2.1-4)&quot;
	.section	.note.GNU-stack,&quot;&quot;,@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

得分: 3

除了使用 exit() 终止程序通常被认为是不良实践之外,你可以尝试以下方法:

int func()
{
    {
        A b;
        /* ... */
    } // 离开作用域 => 销毁 b
    exit(1);
}

PS:假设你不是在编写驱动程序,大多数内核(包括 Microsoft Windows NT、Unix(如 BSD)、XNU(macOS)和 Linux)在程序退出时会自动释放分配的内存。

英文:

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 =&gt; 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.

huangapple
  • 本文由 发表于 2023年2月19日 17:34:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75499173.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定