错误、漏洞、问题 - 页 417

 
joo:

是的,如果有东西需要在return()中返回的话。

或者至少让编译器确定该函数将返回一些东西。

这不仅适用于
switch

但一般来说,对于所有的函数,除了void

试着编译这段代码。

//+----------------------------------------------------------------------------+
//|                                                                  Scale.mqh |
//|                                             Copyright © 2010, JQS aka Joo. |
//|                                           http://www.mql4.com/ru/users/joo |
//|                                        https://www.mql5.com/ru/users/joo |
//——————————————————————————————————————————————————————————————————————————————
double Scale(double In,double InMIN,double InMAX,double OutMIN,double OutMAX)
{
  if (OutMIN==OutMAX)
    return(OutMIN);
  if (InMIN==InMAX)
    return((OutMIN+OutMAX)/2.0);
  else
  {
    if (In<InMIN)
      return(OutMIN);
    if (In>InMAX)
      return(OutMAX);
    //return(((In-InMIN)*(OutMAX-OutMIN)/(InMAX-InMIN))+OutMIN);
  }
}
//——————————————————————————————————————————————————————————————————————————————

它不能编译。

现在解开它。

//return(((In-InMIN)*(OutMAX-OutMIN)/(InMAX-InMIN))+OutMIN);

奇迹就会发生!:)

 
Yedelkin:

根据《手册》,bool是除整数以外的一种特殊类型...这就是为什么我删除了我不正确的声明。虽然我不打算争论--我不是专家。

我指的不是案例标签,而只是枚举(考虑到bool类型是其中最小的)。下面是一个有相同编译错误 的例子。

所以我再重复一下我关于这个例子的问题:你的意思是编译器没有考虑到Triple枚举的值列表和它们的总数吗? 我有来自枚举的所有值用于切换操作符。

根据我的理解,编译器(开发者)正在进行再保险。重点是,如果一个变量没有被明确地初始化,它将根据其类型获得错误的/0 的值(第二个指的是枚举)。

但是,如果我们在执行过程中得到一个超出可能变体范围的值(在Triple的例子中,它可以是-1-+1范围以外的任何值),而没有破坏性的结果,就会出现严重问题。

 
Interesting:

如果违约者被排除在外,该函数应返回什么?

我认为是ENUM_CHART_MODE 枚举的最后一个值。我现在就去检查。

......嗯,它没有发挥作用。打印如下:ChartMode=ENUM_CHART_MODE::-1
 
Interesting:

根据我的理解,编译器(开发者)正在进行再保险。重点是,如果一个变量没有被明确初始化,它将根据其类型被分配虚假/0 的值(第二个是关于枚举)。

但是,如果我们得到一个超出可能变体范围的值(在Triple的例子中,它可能是范围-1-+1之外的任何值),当执行变量而没有任何虔诚的结果时,我们将有一个严重的问题。

这并不完全是重点。看看我以前的帖子。
 
joo:
这并不是真正的重点。看看我以前的帖子。

是的,编译器必须确保它返回一些东西。我认为这是一个合理的保证(特别是在例子中对开关 处理有一个默认)。

如果你不需要返回一个值,那是另一回事。

 
Yedelkin:

我认为最后一个值是来自ENUM_CHART_MODE 枚举。我现在就去看看。

...是的,这没有用。打印如下:ChartMode=ENUM_CHART_MODE::-1

如果你想深入了解所有这些错综复杂的问题,请阅读Björn Straustrup, C++。

说实话,我甚至没有真正读过MQL5的文档--我只是按照C++语言来写。开发人员相当精确地遵循这种语言的标准。

 

下午好!

建466。

我开始,一旦出现连接并下载了几千字节,终端就关闭了。我断开互联网,它不会关闭。

我把/logs/Crash/目录中的文件附上。

有什么办法可以解决这个问题吗?

谢谢

))没有被附上。以下是这段文字。

时间:2011.06.16 10:28 (0:00:11)

程序:客户终端

版本:500.466 (2011年6月9日)

修订版:32925

操作系统:Windows 7专业服务包1(Build 7601)。

处理器:2个AMD Athlon 64 X2双核处理器5000+

内存:911,1983 Mb

虚拟:1815个免费的2047Mb

CrashMD5 : 2219A3BB7215B179256A7E41D40BD511

异常:C0000094在007B41B4 NA到000000处


模块 : 00400000 00B96000 terminal.exe (5.0.0.466)

: 6FDC0000 00027000 wlidnsp.dll (7.250.4225.0)


007B41A0:00014 [007B41B4] #22663(终端.exe)。

774D58FC:00C74 [774D6570] strcspn(ntdll.dll)。

774D58FC:00CAA [774D65A6] strcspn(ntdll.dll)。

74A5DC14:000EC [74A5DD00] func_0x74A5DC14 (dbghelp.dll)。

74A5E10D:0016E [74A5E27B] SymGetLineFromAddr64(dbghelp.dll)。

74A5F73A:0085A [74A5FF94] func_0x74A5F73A(dbghelp.dll)。

74A6189C:000D2 [74A6196E] func_0x74A6189C (dbghelp.dll)。

74A5F73A:00A54 [74A6018E] func_0x74A5F73A(dbghelp.dll)。

74A5DC14:000EC [74A5DD00] func_0x74A5DC14 (dbghelp.dll)。

74A5E10D:0016E [74A5E27B] SymGetLineFromAddr64(dbghelp.dll)。

74A5F73A:0085A [74A5FF94] func_0x74A5F73A(dbghelp.dll)。

74A6189C:000D2 [74A6196E] func_0x74A6189C (dbghelp.dll)。

74A5F73A:00A54 [74A6018E] func_0x74A5F73A(dbghelp.dll)。

774D68C7:000E0 [774D69A7] RtlLogStackBackTrace(ntdll.dll)。

774D58FC:004D7 [774D5DD3] strcspn(ntdll.dll)。


寄存器 : EAX=000000000000 EIP=007B41B4 EFLGS=00010246 ES=0023

: EBX=000000000000 ESP=0012E2CC EBP=0012E320 FS=003b

: ECX=00000000 ESI=04C74C48 CS=001b GS=0000

: edx=000000000000 edi=00000007 ds=0023 ss=0023

 

继续在返回值的函数中使用切换操作符的主题。昨天,得到了一个中间结论,证实了在使用枚举+开关时,使用默认标签成为强制性的。但这里有一个例子,当这个结论被推翻的时候。

enum Triple
  {
   err=-1,
   no = 0,
   hay= 1
  };
Triple triple_var1,triple_var2;
Triple Test(void)
  {
   switch(triple_var1)
     {
      case  err: return(err);
      case   no: return(no);
      case  hay: return(hay);
      default:
         switch(triple_var2)
           {
            case  err: return(err);
            case   no: return(no);
            case  hay: return(hay);
           }
     }
  }
void OnStart()
  {
   Test();
  }
在这里,切换操作符被应用了两次,再次应用时,默认 标签被排除在外(第二层)。假设编译器考虑到在triple_var1和triple_var2变量中找到任何垃圾的可能性,同时不考虑Triple枚举中的值列表和它们的数量,为什么编译器不会在switch运算符的第二层报告错误?我们的中间结论/假设是错误的,或者编译器只限于检查 "第一层 "的运算符?特别是,如果我们把switch(triple_var2)中的标签/标记注释掉,仍然没有错误信息,尽管Test()函数不是void类型的。

如果在switch(triple_var2)操作符(没有默认 标签)之后插入switch(triple_var1)操作符中的任何case标签,也会得到类似的结果。

 
Yedelkin:

继续在返回值的函数中使用切换操作符的主题。昨天,得到了一个中间结论,证实了在使用枚举+开关时,使用默认标签成为强制性的。但这里有一个例子,这个结论被反驳了。

这里的切换操作符被应用了两次,当它被重复应用时(第二层),默认 标签被排除。假设编译器考虑到triple_var1和triple_var2变量中可能存在的垃圾,同时不考虑Triple枚举中的值列表和它们的数量,为什么编译器不会在switch运算符的第二层使用上报错?我们的中间结论/假设是错误的,或者编译器只限于检查 "第一层 "的运算符?特别是,如果我们注释掉switch(triple_var2)的标签/标记,仍然不会出现错误信息,尽管Test()函数不是void类型的。

这是我们的缺陷,谢谢你的发现,我们会修复它。会有一个错误。
检查开关以涵盖所有可能的值,这超出了编译的范围。
作为MQL5的一个 "功能",这很有趣,我们会考虑如何做。
 
该错误已被纠正。
"开关检查器芯片已经讨论过了,它不可能实现有效/正确的控制。
开关表达式的值可以是任何东西,比如说。

enum EV { v1, v2, };

string Test(void)
  {
   switch(EV(3))
     {
      case v1: return("v1");
      case v2: return("v2");
     }
   return("oops");
  }
  
void OnStart()
  {
   Print(Test());
  }