调用 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
调用之前销毁(例如,通过为模拟对象引入另一个范围)。
根据 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
调用之前销毁(例如,通过为模拟对象引入另一个范围)。