我正在开发一个用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;
}
Run Code Online (Sandbox Code Playgroud)
必须使用/ 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
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下,究竟是什么在这里无法到达? 我最好的理论是它是析构函数,但我想要一个确定的答案.
如果我想让这段代码警告清洁,我该如何实现呢? 我能想到的最好的是将其转换为编译时错误.
struct A {
private:
A(); // No, you can't construct …Run Code Online (Sandbox Code Playgroud) 编译器是否在运行时编译MSIL或Native代码中的"无法访问代码"?
我正在开发一个多平台项目,有些平台已经禁用了功能,在这些功能的界面中,我常常做的是这样的事情:
bool Foo::bar() const {
// disabled
abort();
}
Run Code Online (Sandbox Code Playgroud)
GCC/LLVM不要求非void函数返回值(它们只是发出警告),在这种情况下,我调用的地方abort(),它们足够智能甚至不发出警告(因为函数永远不会返回).
有没有办法(编译标志?)使Visual C++ 2010的行为方式相同,所以我不打算破坏Windows版本?我知道我总是可以在中止之后返回值,但是当我在其他平台上工作时,我通常会忘记这一点,并且不给出错误的行为似乎更合适.
当在无限循环之后写入某些语句时,该语句将成为无法访问的代码.例如:
for(;;)
{
}
Sytem.out.println("Test-1"); //unreachable code
Run Code Online (Sandbox Code Playgroud)
但我在这里面临一些困难.
请看下面的两个代码段:
代码片段1:
for(final int z=4;z<6;)
{
}
System.out.println("Test-2"); //unreachable code
Run Code Online (Sandbox Code Playgroud)
这里,最后一个语句必须是不可达的,因为循环是无限的,输出是预期的.
代码片段2:
final int z=4;
for(;;)
{
if(z<2)
break;
}
System.out.println("Test-3"); //not unreachable
Run Code Online (Sandbox Code Playgroud)
从概念上讲,上面代码中的for循环也是无限的,因为z是final,并且if(z<2)仅在编译时确定.if条件永远不会为真且循环永远不会中断.但是,上面代码中的Last语句是无法访问的.
问题:
为什么会这样?
任何人都可以告诉我确切的规则,我们可以看到代码是否无法访问.
我有一个实现许多功能的标记类型。在一种情况下,我需要这些功能之一来进入无限循环。不幸的是,据我所知,我没有办法对其进行编译,从而不会发出警告。我希望仍然使用-gnatwe以确保我的代码中没有警告,但是如何实现这种功能。
该函数如下所示:
function Foo (This : Some_Type) return Some_Type'Class is
begin
loop
Do_Useful_Stuff_Indefinitely_With (This);
end loop;
-- return This; (if needed?)
end Foo;
Run Code Online (Sandbox Code Playgroud)
我试过了,pragma (No_Return)但那仅适用于过程(并且该Foo函数在其他地方用作适当的函数,因此必须具有相同的签名)。
我也尝试过,pragma Suppress (All_Checks)但是仍然对代码无法到达或缺少返回语句错误提出警告。
有什么办法可以使一次性功能永久运行而不会发出警告?
将此库视为依赖项:
[dependencies]
rustengine = "1.0.60"
Run Code Online (Sandbox Code Playgroud)
针对它编译这个小程序:
[dependencies]
rustengine = "1.0.60"
Run Code Online (Sandbox Code Playgroud)
这将实例化库的主要对象,调用昂贵的计算,然后打印它的统计信息。它输出:
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
Running `target\debug\rustengine.exe`
node(s) 320006 , time 0.47 sec(s) , nps 677.4099 kNode(s)/sec
Run Code Online (Sandbox Code Playgroud)
现在在官方 Rust WASM 示例中使用相同的依赖项
https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_wasm
并修改greet函数以针对相同的库依赖项执行相同的两个命令:
use rustenginelib::uci::*;
fn main() {
let mut uci = create_default_uci();
uci.process_uci_command("perft 4".to_string());
}
Run Code Online (Sandbox Code Playgroud)
编译时不会出现警告或错误,npm 包已构建,在 localhost:8080 上提供,WASM 可执行文件运行并失败并出现错误
Uncaught (in promise) RuntimeError: unreachable
at wasm-function[117]:0x1459f
at wasm-function[188]:0x1636d
at wasm-function[232]:0x16792
at wasm-function[9]:0x6692
at wasm-function[52]:0xf068
at Module.greet (webpack:///./node_modules/@easychessanimations/chessengine-wasm/chessengine_wasm_bg.js?:87:68)
at eval (webpack:///./index.js?:3:6)
Run Code Online (Sandbox Code Playgroud)
一旦注释掉昂贵的计算(但不是库对象的初始化),该示例就可以工作:
Finished …Run Code Online (Sandbox Code Playgroud) f0如下所示f1,
long long b;
void f0(int a) {
a %= 10;
if (a == 0) b += 11;
else if (a == 1) b += 13;
else if (a == 2) b += 17;
else if (a == 3) b += 19;
else if (a == 4) b += 23;
else if (a == 5) b += 29;
else if (a == 6) b += 31;
else if (a == 7) b += 37;
else if (a …Run Code Online (Sandbox Code Playgroud) 下面的代码是一个完美的代码的精确副本.不同之处在于此代码放在WCF服务应用程序项目中,而工作代码来自Windows窗体应用程序项目.foreach中的代码是无法访问的,这很奇怪,因为我之前测试过代码并且它有效,返回正确的值
public IEnumerable<Employee> GetStudentDetails(string username,string password)
{
var emp = agrDb.LoginAuthentication(username, password);//procedure in the database thats returning two values
//Namely: EmployeeFirstName and EmployeeLastName
List<Employee> trainerList = new List<Employee>();
foreach (var item in emp)
{
//unreachable code here
Employee employ = new Employee();
employ.EmployeeFirstName = item.EmployeeFirstName;
employ.EmployeeLastName = item.EmployeeLastName;
trainerList.Add(employ);
//trainerList.Add(item.EmployeeLastName);
}
return trainerList;
}
Run Code Online (Sandbox Code Playgroud) 我有以下代码:
private const FlyCapture2Managed.PixelFormat f7PF = FlyCapture2Managed.PixelFormat.PixelFormatMono16;
public PGRCamera(ExamForm input, bool red, int flags, int drawWidth, int drawHeight) {
if (f7PF == FlyCapture2Managed.PixelFormat.PixelFormatMono8) {
bpp = 8; // unreachable warning
}
else if (f7PF == FlyCapture2Managed.PixelFormat.PixelFormatMono16){
bpp = 16;
}
else {
MessageBox.Show("Camera misconfigured"); // unreachable warning
}
}
Run Code Online (Sandbox Code Playgroud)
我知道这段代码是无法访问的,但是我不希望这条消息出现,因为它是编译时的配置,只需要更改常量来测试不同的设置,每像素位数(bpp)会根据像素格式.是否有一个很好的方法让一个变量保持不变,从中导出另一个变量,但不会导致无法访问的代码警告?请注意,我需要两个值,在相机启动时需要将其配置为正确的像素格式,并且我的图像理解代码需要知道图像的位数.
那么,有一个很好的解决方法,还是我只是忍受这个警告?
如果我有类似的代码
public static void main(String args[]){
int x = 0;
while (false) { x=3; } //will not compile
}
Run Code Online (Sandbox Code Playgroud)
编译器将投诉x=3无法访问的代码,但如果我有类似的代码
public static void main(String args[]){
int x = 0;
if (false) { x=3; }
for( int i = 0; i< 0; i++) x = 3;
}
Run Code Online (Sandbox Code Playgroud)
然后它通过内部代码正确编译if statement,for loop无法访问.为什么java工作流逻辑没有检测到这种冗余?任何用例?
unreachable-code ×10
c# ×3
c++ ×2
java ×2
visual-c++ ×2
ada ×1
assembly ×1
c ×1
constructor ×1
foreach ×1
gcc ×1
gnat ×1
if-statement ×1
loops ×1
rust ×1
warnings ×1
wcf ×1
webassembly ×1