构造函数右大括号处无法访问的代码
Unreachable code at constructor's closing brace
>我正在开发一个使用 VC9 构建的应用程序,我遇到了一个我不完全理解的警告:为什么构造函数的右大括号上有"无法访问的代码"警告?
重现该问题的最小测试用例是:
__declspec(noreturn) void foo() {
// Do something, then terminate the program
}
struct A {
A() {
foo();
} // d:foo.cpp(7) : warning C4702: unreachable code
};
int main() {
A a;
}
必须使用/W4 编译才能触发警告。 或者,可以使用/we4702 进行编译,以强制检测此警告时出错。
d:>cl /c /W4 foo.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 15.00.21022.08 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
foo.cpp
d:foo.cpp(7) : warning C4702: unreachable code
有人可以解释一下这里究竟是无法到达的吗? 我最好的理论是它是析构函数,但我想要一个明确的答案。
如果我想使此代码警告干净,我该如何实现? 我能想到的最好的办法就是将其转换为编译时错误。
struct A {
private:
A(); // No, you can't construct this!
};
int main() {
A a;
}
编辑:为澄清起见,使用 noreturn 函数终止程序通常不会导致包含该函数调用的右大括号上出现无法访问的代码警告。
__declspec(noreturn) void foo() {
// Do something, then terminate the program
}
struct A {
A() {
}
~A() {
foo();
}
};
int main() {
A a;
}
结果:
d:>cl /c /W4 foo3.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 15.00.21022.08 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
foo3.cpp
> Gorpik 走在正确的轨道上。 我已经创建了两个类似的测试用例,编译了它们,并反汇编了它们,我想我已经理解了根本原因:构造函数总是隐式生成一个 return 语句,并且由于 noreturn 函数,这个 return 语句无法访问。
noreturn_constructor.cpp
__declspec(noreturn) void foo() {
// Do something, then terminate the program
}
struct A {
A() {
foo();
}
~A() {
}
};
int main() {
A a;
}
noreturn_destructor.cpp
__declspec(noreturn) void foo() {
// Do something, then terminate the program
}
struct A {
A() {
}
~A() {
foo();
}
};
int main() {
A a;
}
diff -u *.disasm
--- noreturn_constructor.disasm 2012-05-30 11:15:02.000000000 -0400
+++ noreturn_destructor.disasm 2012-05-30 11:15:08.000000000 -0400
@@ -2,7 +2,7 @@
Copyright (C) Microsoft Corporation. All rights reserved.
-Dump of file noreturn_constructor.obj
+Dump of file noreturn_destructor.obj
File Type: COFF OBJECT
@@ -35,15 +35,15 @@
??0A@@QEAA@XZ (public: __cdecl A::A(void)):
0000000000000000: 48 89 4C 24 08 mov qword ptr [rsp+8],rcx
- 0000000000000005: 48 83 EC 28 sub rsp,28h
- 0000000000000009: E8 00 00 00 00 call ?foo@@YAXXZ
- 000000000000000E: 48 8B 44 24 30 mov rax,qword ptr [rsp+30h]
- 0000000000000013: 48 83 C4 28 add rsp,28h
- 0000000000000017: C3 ret
+ 0000000000000005: 48 8B 44 24 08 mov rax,qword ptr [rsp+8]
+ 000000000000000A: C3 ret
??1A@@QEAA@XZ (public: __cdecl A::~A(void)):
0000000000000000: 48 89 4C 24 08 mov qword ptr [rsp+8],rcx
- 0000000000000005: C3 ret
+ 0000000000000005: 48 83 EC 28 sub rsp,28h
+ 0000000000000009: E8 00 00 00 00 call ?foo@@YAXXZ
+ 000000000000000E: 48 83 C4 28 add rsp,28h
+ 0000000000000012: C3 ret
Summary
无法访问的代码是这个隐式 return 语句,它是在构造函数中生成的,而不是在析构函数中生成的:
- 000000000000000E: 48 8B 44 24 30 mov rax,qword ptr [rsp+30h]
+ 0000000000000005: 48 8B 44 24 08 mov rax,qword ptr [rsp+8]
在A::A()
末尾没有要调用的析构函数,所以这不是问题。无法到达的是对象的实际构造,这发生在构造函数完成其执行之后。由于它永远无法完成,因此无法访问编译器生成的代码。
foo 上的 declspec(noreturn) 正在产生此警告。 你告诉编译器此函数不会返回。 因此,编译器会发出构造函数永远不会完成的警告。
参见 http://msdn.microsoft.com/en-us/library/k6ktzx3s(v=vs.80).aspx
"这个__declspec属性告诉编译器函数不返回。因此,编译器知道调用 __declspec(noreturn) 函数后的代码无法访问。
右大括号可能会生成代码(如调用析构函数),这些代码将无法访问。
- 我的简单if-else语句是如何无法访问的代码
- 访问被拒绝后,c++中的故障保护代码
- 为什么示例代码访问IUnknown中已删除的内存
- 使用 g++7 构建的代码在访问未对齐的内存时崩溃
- 无法访问的代码 在 C++11 中,可能导致这种情况的原因是什么?
- 提供对不同类型的数据(建议、代码审查)的线程安全访问的类
- 无法访问的代码如何导致我的程序崩溃?
- 是否可以访问代码中的调用堆栈?
- C++/CLI访问字符串::来自非CLI代码的格式
- Java 本机访问代码错误:"Invalid memory access"
- 访问C 代码中的PWD
- 我们还能使用任何其他方法来访问Android中的C 代码,而不是使用JNI访问C 代码
- 如何将DLL访问代码从C++移植到C#
- 警告级别4中的不可访问代码警告
- 使用.open()成员函数C++的ifstream数组的错误访问代码
- 在 Apache Cordova for Android 中访问C++代码
- 错误的访问代码 1 glDrawElements
- 外部"C"访问代码的函数
- 访问代码中的Makefile变量
- 使用Unicode终止符的QString中的访问代码