调用 exit(0) 时如何在 google 模拟对象之后正确清理?

How to properly cleanup after google mock objects when calling exit(0)?

根据 https://docs.microsoft.com/en-us/cpp/cpp/program-termination?view=msvc-170#exit-function" 从主函数发出 return 语句等同于以 return 值作为参数调用退出函数。 ".

但事实证明这是错误的,如下例所示:

main.cpp

#include "gtest/gtest.h"
#include "gmock/gmock.h"
 
#include "MyClass.h"  // defines a class named `MyClass`
#include "mock_test.h"
 
using ::testing::_;
using ::testing::Return;
 
int main(int argc, char **argv)
{
    Mock_MyClass mock_;
    EXPECT_CALL(mock_, foo(_))
        .WillRepeatedly(Return(0));
 
    exit(0);
}

mock_test.h

class Mock_MyClass : public MyClass
{
public:
    MOCK_METHOD(int, foo, (string& _), (override));
};

假设MyClass定义了一个虚拟析构函数和一个方法virtual int foo(string &)(但MyClass的全部内容不相关)。

根据运行上述源代码生成的程序,我系统地得到以下错误:

错误:应该删除此模拟对象,但从未删除。它的地址是@0000000001100EF0。 错误:在程序退出时发现 1 个泄漏的模拟对象。

但是,如果将 exit(0) 替换为 return 0,我将不再收到此错误。

因此调用 exit(0) 似乎绕过了使用 return 0 时发生的一些清理过程。

如何使用 exit(0) 在 google 模拟对象之后以与使用 return 0 相同的方式清理程序?这将使人们能够通过调用 exit(0) 来终止子函数的程序执行,同时确保不会出现上述错误。

(我为 Linux、armv7、-std=c++17 编译)

这似乎是专门针对 MSVC 编译器的信息。 std::exit 上的 cppreference 说:

Stack is not unwound: destructors of variables with automatic storage duration are not called.

为了比较,提到了片刻之后从main返回:

Returning from the main function, either by a return statement or by reaching the end of the function performs the normal function termination (calls the destructors of the variables with automatic storage durations) and then executes std::exit, passing the argument of the return statement (or ​0​ if implicit return was used) as exit_code.

符合C++标准support.start.term

[...] (Objects with automatic storage duration are not destroyed as a result of calling exit().)

所以调用这些析构函数的唯一标准方法是

  • 将对象存储持续时间更改为静态(thread_local 可能有效,我不确定)或
  • 使用 return 而不是 std::exit
  • 确保在 std::exit 调用之前销毁(例如,通过为模拟对象引入另一个范围)。