错误、漏洞、问题 - 页 2591

 
Koldun Zloy:

如果复制的字符串大于或小于分配的缓冲区大小,会发生什么?

如果小一点也没关系,通常字符串缓冲区 总是比字符串本身略大(但这不是事实!)。

但如果你写得多了,几乎可以保证终端会崩溃。
崩溃很可能不会立即发生,而只是在下一次使用动态内存工作时(重新分配数组或字符串缓冲区)或在关闭时,当使用过的MQL程序内存返回到系统时才会发生。

 
Ilyas:

1.在MQL中只有Unicode,这就是为什么字符大小为2字节的原因。

2.字符串是一个结构(4字节的缓冲区大小和8字节的指针大小)。


复制到字符串应该是

如果它不工作,错误必须在其他地方找到

是的,最简单的函数

wcscpy(out, data);

并造成问题。这条线被均匀地复制,但有很大的跳动。也就是说,在复制过程中会有延迟。
这就是为什么尝试了其他的功能,如果正确使用,也会造成这个问题。
各种各样的mutex、recursive_mutex、lock_guard都不能解决跳过问题。

由于这个原因,我不知道该怎么想了,从插座上传来的字符串是正确的。
收到wchar_t*类型的字符串,自动意味着它是Unicode编码的,并且字符串中的每个字符等于2个字节(已测试)。
但我不明白,wchar_t*指针会被复制到8个字节和12个字节的字符串中。
也许是操作系统的位模式在某种程度上影响了它?一切都在64位版本、Windows和Linux上检查。

 

我不明白,什么是空隙? 空白线?

你是把所有的线程都写到同一个MQL行,还是写到不同的行?

在MQL代码中,你什么时候决定在字符串中存在数据,并且可以被处理/输出?


如果所有的东西都在一行中,这是不对的,那么你需要在DLL侧有一个关键部分,可以从MQL和行变化计数器中访问该部分。


来自MQL的伪装代码

#import ...
   bool LockValueIfChanged();
   void UnlockValue();
#import


while(!_IsStopped())
  {
   if(LockValueIfChanged())
     {
      Print( Value );
      UnlockValue();
     }
  }

DLL

uint64_t last_mql_counter=0;
uint64_t counter=0;

bool LockValueIfChanged()
  {
   Lock(cs);

   if(last_mql_counter!=counter)
    {
     last_mql_counter=counter;
     return(true);
    }

   Unlock(cs);
   return(false);
  }

void UnlockValue()
  {
   Unlock(cs);
  }

Thread()
  {
   while( running )
     {
      Lock(cs);

      Value = ...

      counter++;

      Unlock(cs);
     }
  }


这是一个例子,从MQL方面会跳过一些行(不是所有的行都会到达MQL,其中一些会被覆盖)。

 
Ilyas:

我不明白,什么是空隙? 空白线?

你是把所有的线程都写到同一个MQL行,还是写到不同的行?

在MQL代码中,你什么时候决定在字符串中存在数据并且可以处理/输出?


如果所有的东西都在一行中,这是不对的,那么你需要在DLL侧有一个关键部分,可以从MQL和行变化计数器中访问该部分。


来自MQL的伪装代码

DLL


这是一个例子,从MQL方面会跳过一些行(不是所有的行都会到达MQL,其中一些会被覆盖)。

是的空行,你可以在截图上看到。
是的,从所有螺纹到一个MQL线。因为在飞行中为字符串创建变量也是有问题的。
如果我们事先不知道会有多少个来源,这些字符串来自哪里,换句话说,是动态的。
我也在思考关键部分,我也认为MQL应该阻止一些阅读的方式。谢谢你的例子,我将仔细考虑。
但事实证明,你还是建议在自己的独立变量中获得每个字符串的来源?而不是在MQL的一个变量中。
只是,从一个字符串变量中处理所有线程的接收数据更方便。
我以为,如果在dll方面有一个写锁,在MQL中,读不需要锁,也就是说,MQL好像考虑到了这样的复制实现。
但是,即使我从一个线程中得到了一个字符串,我仍然得到了跳过!
如果我使用其他参数正确的复制函数,不管是一个还是几个线程,我都不会得到跳过,但我仍然会得到一个不均匀的字符串。
如果你使用了错误的参数,字符串是均匀的,但它开始泄漏。

附加的文件:
458.png  71 kb
 
Ilyas:

如果少一点也没关系,通常字符串缓冲区 总是比字符串本身略大(但这不是事实!)。

但是,如果你写得更多,几乎可以肯定会出现终端崩溃。
崩溃很可能不会立即发生,而只是在下一次动态内存操作(重新分配数组或字符串缓冲区)或关闭时,当MQL程序使用的内存返回到系统时才会发生。

那你为什么建议新人使用wcscpy 函数

有更安全的函数:wcscpy_s, wmemcpy_s。

 

请解释为什么在OnCalculate处理程序中,每个新形成的条形图的时间[0]比我们用SymbolInfoTick函数要求的tick时间要早?SymbolInfoTick函数 应该总是返回最后一个已知的刻度。

我附上一个指标,它在汗水模式的测试器中再现了这个问题。

2019.10.12 16:51:53.667 2019.01.02 06:00:00   Time 2019.01.02 06:00:00 = 1546408800000 is ahead of tick:  1546297199572
2019.10.12 16:51:53.753 2019.01.02 06:01:00   Time 2019.01.02 06:01:00 = 1546408860000 is ahead of tick:  1546408830000
2019.10.12 16:51:54.315 2019.01.02 06:02:00   Time 2019.01.02 06:02:00 = 1546408920000 is ahead of tick:  1546408919000
2019.10.12 16:51:54.617 2019.01.02 06:03:00   Time 2019.01.02 06:03:00 = 1546408980000 is ahead of tick:  1546408979000

在每个酒吧的边界,都有这个问题。

PS。而根据文档,OnCalculate是对所有的ticks无遗漏地调用的,tick volume应该总是与ticks counter相吻合,但这并不总是真的。
附加的文件:
fake.mq5  2 kb
 
Stanislav Korotky:

请解释一下为什么在OnCalculate处理程序中,每个新形成的柱状体的时间[0]比我们用SymbolInfoTick函数请求的tick时间要早?SymbolInfoTick函数 应该总是返回最后一个已知的刻度。

我附上一个指标,它在汗水模式的测试器中再现了这个问题。

在每个条形边界上都有这个问题。

PS。另外,这个指标还显示了另一个问题:有tick计数,从文件中的说法来看,OnCalculate是对所有tick无遗漏地调用的,tick量应该总是与tick计数器相吻合,但情况并非总是如此。

请告诉我建造号。

 
Slava:

请告诉我建造号

2093

 
Stanislav Korotky:

2093

你描述的问题已经在Build 2155中得到了修复。

 

在编辑器中找到了高亮的常数SYMBOL_CHART_MODE_OLD

当然,它不在ENUM_SYMBOL_CHART_MODE 中。

它是什么?

Документация по MQL5: Константы, перечисления и структуры / Состояние окружения / Информация об инструменте
Документация по MQL5: Константы, перечисления и структуры / Состояние окружения / Информация об инструменте
  • www.mql5.com
Для получения текущей рыночной информации служат функции SymbolInfoInteger(), SymbolInfoDouble() и SymbolInfoString(). В качестве второго параметра этих функций допустимо передавать один из идентификаторов из перечислений ENUM_SYMBOL_INFO_INTEGER, ENUM_SYMBOL_INFO_DOUBLE и ENUM_SYMBOL_INFO_STRING соответственно. Некоторые символы (как...