Features of the mql5 language, subtleties and tricks - page 318

 

So, what happens at  Print("Error in ", LOCATION)

Print("Error in ", LOCATION)  is expanded to  Print("Error in ", __FILE__ " : " STR(__LINE__))

STR(__LINE__)  has no stringification operation, i.e. there is no  #x  in it's expansion, but there is an  x , so it has to evaluate  x  and input the value of __LINE__ to  ST2  for stringification. It expands to  ST2(11)  which in turn will stringify the number 11, since it is using  #x

So, techniqually speaking:

  • Using a single layer indirection  ST2(x) #x  stringifies the inputted macro's name (for example: "__LINE__")
  • but by using double layers, it will stringify the inputted macro's value. (for example: "11")
 
amrali #:



    #define __SOURCE__ __FILE__ + " (" + (string)__LINE__ + ") " + __FUNCTION__
     

    Forum on trading, automated trading systems and testing trading strategies

    Features of the mql5 language, subtleties and tricks

    amrali, 2025.11.04 11:40

    struct STRUCT
    {
      int Value;
    
      void Func( int ) {}
    };
    
    #define  MACROS(A) Struct##A
    #define  MACROS2(A) MACROS(A)
    
    void OnStart()
    {
      STRUCT Struct;
    
      MACROS(.Value) = 0; // The first entry is OK.
      MACROS(.Func(0));   // The second entry is OK.
    
      MACROS2(.Func(MACROS2(.Value))); // First and second entry together - undeclared identifier.
    }
    

    Solution: use a 2nd level macro (for indirection).

    This was discussed before here and here.

    Additionally, to debug macro expansions in MQL:
    //+------------------------------------------------------------------+
    //| Print the macro expansion using Stringizing operator #           |
    //+------------------------------------------------------------------+
    #define STRINGIFY(s) #s
    #define EXPAND_MACRO(macro)  Print(STRINGIFY(macro))
    
    struct STRUCT
    {
      int Value;
    
      void Func( int ) {}
    };
    
    #define  MACROS(A) Struct##A
    #define  MACROS2(A) MACROS(A)
    
    void OnStart()
    {
      STRUCT Struct;
    
      //MACROS(.Func(MACROS(.Value))); // Compile error
      MACROS2(.Func(MACROS2(.Value))); // OK.
    
      EXPAND_MACRO(MACROS(.Func(MACROS(.Value))));
      EXPAND_MACRO(MACROS2(.Func(MACROS2(.Value))));
    }
    

    Output:

    2025.11.07 12:46:29.155 Nested (EURUSD,H1)      Struct.Func(MACROS(.Value))
    2025.11.07 12:46:29.155 Nested (EURUSD,H1)      Struct.Func(Struct.Value)
    
     

    If you press Stop during optimisation, the descriptors of interrupted passes remain open, because code execution is strictly interrupted, preventing the logic of closing descriptors - CloseHandle - from being executed.

    Moreover, this situation may occur during debugging, when debug closure is in progress. In general, there are scenarios in which descriptors are not closed.


    I searched for a long time on the Internet for ways to close descriptors. In particular, in the case of using File Mapping.

    Found only a formulation of the same problem without an answer.


    For example, if the process was interrupted before CloseHandle, such a function will always return true on the next runs.

      static bool IsExist( const string Name = __FILE__ )
      {
        const HANDLE handle = kernel32::OpenFileMappingW(FILE_MAP_ALL_ACCESS, 0, Name);
      
        if (handle)
          kernel32::CloseHandle(handle);
    
        return((bool)handle);
      }


    Is it possible to somehow free memory/file in case of open handles hanging? Now the problem is solved only by reloading the process - Terminal.

    CreateFileMapping() returning "already exists" even after reboot; how to remove old Named Shared Memory?
    CreateFileMapping() returning "already exists" even after reboot; how to remove old Named Shared Memory?
    • 2012.10.03
    • Blake Senftner
    • stackoverflow.com
    I have a series of Slave exe's controlled by a Master exe via usage of Named Shared Memory created with CreateFileMapping() and MapViewOfFile(). I was debugging the Master via Visual Studio, and when I got what I needed I simply told Visual Studio to "stop debugging". Bad move, because that Named Shared Memory was left active, and it is still...
     
    fxsaber # :
    Is it possible to free memory/file if open descriptors are hanging? Right now the problem is solved only by reloading the process - Terminal.
    Is it possible to reuse an existing Handle?
     
    amrali # :
    Also, for debugging macro extensions in MQL:

    Conclusion:

    Thanks, great advice.
     
    hini #:
    Can an existing Handle be reused?
    Sometimes you can, but it's just a coincidence.
     
    fxsaber #:

    Is it possible to free memory/file if open descriptors are hanging? Now the problem is solved only by reloading the process - Terminal.

    Simple playback.
    Новая версия платформы MetaTrader 5 build 5370: улучшения в веб-версии
    Новая версия платформы MetaTrader 5 build 5370: улучшения в веб-версии
    • 2025.11.09
    • www.mql5.com
    В пятницу 17 октября 2025 года будет выпущена обновленная версия платформы MetaTrader 5...
     
    fxsaber #:
    If you press Stop during optimisation, the descriptors of interrupted passes remain open

    Handle command line utility from Sysinternals won't help?

    If you need to use WinAPI, you can do UnmapViewOfFile and CloseHandle (both are required). I don't know in detail, I haven't analysed it.

     
    Edgar Akhmadeev #:

    The Handle command line utility from Sysinternals won't help?

    You need to use WinAPI.

    If you need to use WinAPI, you can do UnmapViewOfFile and CloseHandle (both are required). I don't know in detail, I haven't analysed it.

    Here you can find more details.

    Библиотеки: File Mapping без DLL
    Библиотеки: File Mapping без DLL
    • 2023.03.26
    • www.mql5.com
    File Mapping без DLL: Автор: o_o...