Critical error

 

Есть советник который вызывает функцию из внешней ДЛЛ.
С таким прототипом

#import "myDllTest.dll"
string getMsg(string username, string pass, string server, string port, string type);
#import


В 90% случаев, все работает и советник торгует без проблем. Но иногда МТ4 умирает, вот с такими надписями.
Как можно попытаться определить причину такого поведения МТ4? У кого какие идеи, как отловить ошибку?

There has been a critical error
Time : 2007.03.22 18:48
Program : Client Terminal
Version : 4.00 (build: 202, 06 Feb 2007)
Owner : Alpari Ltd. (MetaTrader - Alpari)
OS : Windows XP Professional 5. 1 Service Pack 2 (Build 2600)
Processors : 1, type 586, level 15
Memory : 523632/240956 kb
Exception : C0000005
Address : 004544A3
Access Type : read
Access Addr : 02AF67EC


Registers : EAX=00000000 CS=001b EIP=004544A3 EFLGS=00010246
: EBX=01D47064 SS=0023 ESP=02A8FAC4 EBP=02AF67EC
: ECX=FFFFFFFF DS=0023 ESI=01CE8F58 FS=003b
: EDX=01CFCD30 ES=0023 EDI=02AF67EC GS=0000

Stack Trace : 00000000 00000000 00000000 00000000
: 00000000 00000000 00000000 00000000
: 00000000 00000000 00000000 00000000
: 00000000 00000000 00000000 00000000
Modules :
1 : 00400000 007A8000 E:\Program Files\MetaTrader 4\terminal. exe
2 : 02A90000 00057000 E:\Program Files\MetaTrader 4\experts\libraries\myDllTest. dll
3 : 10000000 0000D000 C:\WINDOWS\system32\hplun. dll
4 : 20000000 002CD000 C:\WINDOWS\system32\xpsp2res. dll
5 : 5B260000 00038000 C:\WINDOWS\system32\UxTheme. dll
6 : 61EC0000 0000E000 C:\WINDOWS\system32\MFC42LOC. DLL
7 : 698B0000 00058000 C:\WINDOWS\system32\hnetcfg. dll
8 : 71A30000 00040000 C:\WINDOWS\system32\mswsock. dll
9 : 71A70000 00008000 C:\WINDOWS\System32\wshtcpip. dll
10 : 71A80000 00008000 C:\WINDOWS\system32\WS2HELP. dll
11 : 71A90000 00017000 C:\WINDOWS\system32\WS2_32. dll
12 : 73D90000 000FE000 C:\WINDOWS\system32\MFC42. DLL
13 : 746E0000 0004B000 C:\WINDOWS\system32\MSCTF. dll
14 : 76350000 00005000 C:\WINDOWS\system32\MSIMG32. dll
15 : 76380000 00049000 C:\WINDOWS\system32\comdlg32. dll
16 : 76B20000 0002E000 C:\WINDOWS\system32\WINMM. dll
17 : 76F10000 00027000 C:\WINDOWS\system32\DNSAPI. dll
18 : 76F50000 0002D000 C:\WINDOWS\system32\WLDAP32. dll
19 : 76FA0000 00008000 C:\WINDOWS\System32\winrnr. dll
20 : 76FB0000 00006000 C:\WINDOWS\system32\rasadhlp. dll
21 : 77110000 0008C000 C:\WINDOWS\system32\OLEAUT32. dll
22 : 773C0000 00102000 C:\WINDOWS\WinSxS\x86_Microsoft. Windows. Common-Controls_6595b64144ccf1df_6. 0.2600.2180_x-ww_a84f1ff9\comctl32.dll
23 : 774D0000 0013C000 C:\WINDOWS\system32\ole32. dll
24 : 77C00000 00058000 C:\WINDOWS\system32\msvcrt. dll
25 : 77D30000 00090000 C:\WINDOWS\system32\USER32. DLL
26 : 77DC0000 000AC000 C:\WINDOWS\system32\ADVAPI32. dll
27 : 77E70000 00091000 C:\WINDOWS\system32\RPCRT4. dll
28 : 77F10000 00046000 C:\WINDOWS\system32\GDI32. dll
29 : 77F60000 00076000 C:\WINDOWS\system32\SHLWAPI. dll
30 : 7C800000 000F6000 C:\WINDOWS\system32\kernel32. dll
31 : 7C900000 000B1000 C:\WINDOWS\system32\ntdll. dll
32 : 7C9C0000 00818000 C:\WINDOWS\system32\SHELL32. dll

Call stack :
00454480:0023 [004544A3] ?SetReturnedString@CExpertInterior

 
А что Вы возвращаете в качестве string из своей dll?

В общем случае нельзя возвращать из DLL собственные MQL строки, так как Вы не имеет доступа к внутренним пулам памяти под строки и не можете правильно формировать память под строку. Если Вы обманете среду исполнения MQL4 и подсунете ей собственный MQL string, то наверняка будет ошибка при работе с памятью. Что и происходит при попытки взять (SetReturnedString@CExpertInterior) Вашу возвратную строку.

Если Вы работаете со строками, то Вы должны заранее из MQL4 выделить строку достаточного размера и передать ее по ссылке в свою DLL. И уже в DLL заполнять (но не перераспределять!) строку в определенном размере.
 

Используется такой код советника и ДЛЛ (С++)

// MQL ===========================================
 
   string in_s;   // input data
   in_s = getMsg("param1","param1","param","param","param");
 
// C++ ===========================================
  String os; // out string
  ...
  return os.c_str();
Коректен ли он?
Или я должен создавать в MQL строку, потом, что-то типа new() делать под нее (а есть ли подобее этого оператора) и эту строку передавать по ссылке в ДЛЛ?

// C++
char* __stdcall getMsg(char* in_param, char* in_param, char* in_param, char* in_param, char* in_param, char* out);
 
 
// MQL
string string_from_dll; // Create string
getMessages("in","in","in","in","in", &string_from_dll);
Такой код будет коректен с точки зрения MQL, и как выделить память под строку в MQL?

Спасибо, что ответили.
 
Будет ли работа стабильнее, елсли обмен данными сделать через файл?
Т.е. моя программа пишет данные в файл, а советник уже парсит его.
 
Вы в MQL4 выделяете строку большого размера и передаете ссылку на эту строку в DLL.
 

А как выделить память под большую строку, каким оператором?
А то в разделах доки, ничего не нашел как это сделать:
https://docs.mql4.com/ru/basis/types/string
https://docs.mql4.com/ru/strings

 
string big_string="                                                                                                                           ";
 

Что-то после последнего обновления участилось появления сообщения:

There has been a critical error
Time        : 2007.04.03 12:16
Program     : Client Terminal
Version     : 4.00 (build: 203, 28 Mar 2007)
Owner       : Alpari Ltd. (MetaTrader - Alpari)
OS          : Windows XP Professional 5.1 Service Pack 2 (Build 2600)
Processors  : 1, type 586, level 15
Memory      : 523632/207760 kb
Exception   : C0000005
Address     : 00454CF3
Access Type : read
Access Addr : 029F5270
 
Registers   : EAX=00000000 CS=001b EIP=00454CF3 EFLGS=00010246
            : EBX=01D5209C SS=0023 ESP=02CEFAC4 EBP=029F5270
            : ECX=FFFFFFFF DS=0023 ESI=01CE9720 FS=003b
            : EDX=01D04B48 ES=0023 EDI=029F5270 GS=0000
 
Stack Trace : 00000000 00000000 00000000 00000000
            : 00000000 00000000 00000000 00000000
            : 00000000 00000000 00000000 00000000
            : 00000000 00000000 00000000 00000000
Modules     :
          1 : 00400000 007AF000 E:\Program Files\MetaTrader 4\terminal.exe
          2 : 02370000 00013000 E:\Program Files\ABBYY Lingvo 10 Multilingual Dictionary\LvHook.dll
          3 : 02990000 0005A000 E:\Program Files\MetaTrader 4\experts\libraries\getMessages.dll
          4 : 10000000 0000D000 C:\WINDOWS\system32\hplun.dll
          5 : 20000000 002CD000 C:\WINDOWS\system32\xpsp2res.dll
          6 : 5B260000 00038000 C:\WINDOWS\system32\UxTheme.dll
          7 : 61EC0000 0000E000 C:\WINDOWS\system32\MFC42LOC.DLL
          8 : 698B0000 00058000 C:\WINDOWS\system32\hnetcfg.dll
          9 : 71A30000 00040000 C:\WINDOWS\system32\mswsock.dll
         10 : 71A70000 00008000 C:\WINDOWS\System32\wshtcpip.dll
         11 : 71A80000 00008000 C:\WINDOWS\system32\WS2HELP.dll
         12 : 71A90000 00017000 C:\WINDOWS\system32\WS2_32.dll
         13 : 73D90000 000FE000 C:\WINDOWS\system32\MFC42.DLL
         14 : 746E0000 0004B000 C:\WINDOWS\system32\MSCTF.dll
         15 : 76350000 00005000 C:\WINDOWS\system32\MSIMG32.dll
         16 : 76380000 00049000 C:\WINDOWS\system32\comdlg32.dll
         17 : 76B20000 0002E000 C:\WINDOWS\system32\WINMM.dll
         18 : 76F10000 00027000 C:\WINDOWS\system32\DNSAPI.dll
         19 : 76F50000 0002D000 C:\WINDOWS\system32\WLDAP32.dll
         20 : 76FA0000 00008000 C:\WINDOWS\System32\winrnr.dll
         21 : 76FB0000 00006000 C:\WINDOWS\system32\rasadhlp.dll
         22 : 77110000 0008C000 C:\WINDOWS\system32\OLEAUT32.dll
         23 : 773C0000 00102000 C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.2180_x-ww_a84f1ff9\comctl32.dll
         24 : 774D0000 0013C000 C:\WINDOWS\system32\ole32.dll
         25 : 77C00000 00058000 C:\WINDOWS\system32\msvcrt.dll
         26 : 77D30000 00090000 C:\WINDOWS\system32\USER32.DLL
         27 : 77DC0000 000AC000 C:\WINDOWS\system32\ADVAPI32.dll
         28 : 77E70000 00091000 C:\WINDOWS\system32\RPCRT4.dll
         29 : 77F10000 00046000 C:\WINDOWS\system32\GDI32.dll
         30 : 77F60000 00076000 C:\WINDOWS\system32\SHLWAPI.dll
         31 : 7C800000 000F6000 C:\WINDOWS\system32\kernel32.dll
         32 : 7C900000 000B1000 C:\WINDOWS\system32\ntdll.dll
         33 : 7C9C0000 00818000 C:\WINDOWS\system32\SHELL32.dll
 
Call stack  :
00454CD0:0023 [00454CF3] ?SetReturnedString@CExpertInterior
Вызов функции ид MQL таков, и вот кусок кода который в ДЛЛ отвечает за возврат строки. Коректен ли он?

   // input data
   string in_s = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
   in_s = getMessages("param1","param","param","param","param");
 
// C++
char* __stdcall getMessages(.....) {
  String os; // Output String
....
  return os.c_str();
}
 

Как MT4 пишет в лог-файл, в какой момент? Для отладки я написал функцию, которая пишет в лог-файл, все мои действия. Если советник работает - лог есть. НО если возникает critical error то лог пуст. Почему? Если я использую комбинацию - FileWrite, FileFlush.

void DEBUG(string s)
{
   if(bDebug) Print(s);
 
   if(bDebugFile == false) return;
   if(nFileHandler == -1) return;
 
   FileWrite(nFileHandler, GetCurrentDateTime() + " " + s);
   FileFlush(nFileHandler);
}
 
 
// Использую:
 
   DEBUG("Call dll function getMessages");
 
   // input data
   string in_s = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
   in_s = getMessages("param","param","param","param","param");
 
   DEBUG("Successful call dll. Input string: " + s);
 
Bug:

Что-то после последнего обновления участилось появления сообщения:

Вызов функции ид MQL таков, и вот кусок кода который в ДЛЛ отвечает за возврат строки. Коректен ли он?

   // input data
   string in_s = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
   in_s = getMessages("param1","param","param","param","param");
 
// C++
char* __stdcall getMessages(.....) {
  String os; // Output String
....
  return os.c_str();
}


Повторю еще раз - "вы не можете возвращать MQL4 строки из своих DLL через return(string)". Это 100% однозначно.
 

Возврат строк - это вообще тонкое дело. Например, если объект os распределён на стеке, то при возврате из функции он будет уничтожен. Соответственно указатель, возвращаемый функцией os.c_str() будет указывать неизвестно куда в тот момент, когда мы начнём этот указатель обрабатывать уже в своей, вызывающей, функции