Fehler, Irrtümer, Fragen - Seite 2540

 
Сергей Таболин:

Was wollen Sie?

Damit inkompetente Leute wie Sie, Fedoseyev usw. sich mit ihren Kommentaren nicht in die Diskussion über Fehler und Designs einmischen.

Dass Konstruktionen und Mechanismen, die in MQL vollständig aus C++ übernommen wurden und genauso aussehen wie in C++, genauso funktionieren wie in C++.

Sergej Tabolin:

Damit MQL ein vollwertiges Analogon zu C++ ist?

Es ist Blödsinn und Sie wissen es, aber Sie müssen es sagen.
Sergej Tabolin:

Und hören Sie auf zu jammern und Rotzblasen darüber zu machen. Für solche "Diskussionen" habe ich einen eigenen Thread eröffnet.

Sie sind derjenige, der sich darüber beklagt, wie lästig es ist, eine eigene Sprache und einen eigenen Thread zu haben.

Eröffnen Sie einen eigenen Thread für sich und Ihre Sympathisanten und jammern Sie dort.

 
Wie kann ich das Terminal dazu bringen, die mqd-Datei freizugeben? Oder noch besser, wenn es eine interne Möglichkeit gäbe, sie aus der Schnittstelle zu löschen?
 
Stanislav Korotky:
Wie kann ich das Terminal dazu bringen, die mqd-Datei freizugeben? Oder noch besser, wenn es eine interne Möglichkeit gäbe, sie aus der Schnittstelle zu entfernen?

Ich kann ungefähr erraten, worum es in der Frage geht. Es ist besser, sie neu zu formulieren.

 
Ich glaube, es gibt ein Problem mit der Deinitialisierung von DLLs in Services, helfen Sie mir zu verstehen.
Das Problem ist folgendes. Nach dem Drücken des Befehls "Stop" im Menü "Service" wartet das Terminal aus irgendeinem Grund nicht auf das Ende der Funktion Fn().
Es versucht, die Verbindung mit der DLL vorzeitig zu unterbrechen, wobei das Terminal aufgehängt wird oder vollständig abstürzt (geschlossen wird).
Obwohl am DllMain-Einstiegspunkt das Detach-Flag in DLL_PROCESS_DETACH explizit ein Flag zum Beenden der while-Schleife setzt.

Aber while hat keine Zeit, die Schleife rechtzeitig zu verlassen, um die nachfolgenden Funktionen auszuführen, nachdem alle anderen Prozesse zusätzlich abgeschlossen sind.
Und beenden Sie die Funktion Fn() selbst.
Die Funktion DestroyFunction(); dient in diesem Beispiel als Kontrolle.

Der Inhalt der DLL

#define  EXP extern "C" __declspec(dllexport)

void DestroyFunction(void);
EXP void __stdcall Fn(int num);

bool Detach;

//---------------------------------------------------------------------
BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
        switch (ul_reason_for_call)
        {
                case DLL_PROCESS_ATTACH:
                        Detach = false;
                        break;
                case DLL_THREAD_ATTACH:
                        break;
                case DLL_THREAD_DETACH:
                        break;
                case DLL_PROCESS_DETACH:
                        Detach = true;
                        break;
        }
        return TRUE;
}

//---------------------------------------------------------------------
void DestroyFunction()
{
        MessageBoxW(NULL, L"Start DestroyFunction", L"OK", MB_OK);

        return;
}

//---------------------------------------------------------------------
EXP void __stdcall Fn(int num)
{
        int count = num;

        while (Detach == false)
        {
            //Имитация работы цикла
            count++;    

            if (count > 0)
                MessageBoxW(NULL, L"Start While iteration", L"OK", MB_OK);

            Sleep(10000);
        }       

 
        //После нажатия команды "Остановить" в меню Сервис, сюда уже не доходим, так как уже висим, или вылетел терминал.
        DestroyFunction();

        
        return;
}


Der Inhalt des Programms Service.
Eine zusätzliche Verzögerung durch _StopFlag ist nicht hilfreich.

//+------------------------------------------------------------------+
//|                                                      BugDll.mq5 |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property service
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property script_show_inputs


#import "BugDll.dll"
   void Fn(int num);
#import


//+------------------------------------------------------------------+
//| Service program start function                                   |
//+------------------------------------------------------------------+
int OnStart()
{      
   
   Fn(0);

   if(_StopFlag)
      Sleep(10000);
   
   return(0);
}
//+------------------------------------------------------------------+
Dateien:
MQL5.zip  54 kb
 
Roman:
Ich glaube, es gibt ein Problem mit der Deinitialisierung der dll in Services, helfen Sie mir.

die DLL wird nicht (notwendigerweise) sofort nach Beendigung des Dienstes entladen (ich könnte mich irren)

In jedem Fall ist das, was Sie mit DLL_PROCESS_DETACH tun, zu spät. Erstellen Sie eine explizite Deinit-Funktion in der DLL, die diese Markierung setzt, und rufen Sie sie explizit auf, wenn der Dienst endet.

 
Roman:

Das Terminal beginnt mit dem Entladen der Bibliothek, nachdem der Thread von start() zurückkehrt, denke ich. Wie funktioniert es sonst? Das Programm wird ausgeführt und beginnt, seine Umgebung zu zerstören? Das ist Unsinn. Starten Sie einen separaten Thread in der Lib, ohne einen Skript-Thread in einer Schleife zu verfolgen, und er wird normal beendet werden können.

 
Vict:

Das Terminal beginnt mit dem Entladen der Bibliothek, nachdem der Thread von start() zurückkehrt, denke ich. Wie funktioniert es sonst? Das Programm wird ausgeführt und beginnt, seine Umgebung zu zerstören? Das ist Unsinn. Starten Sie einen separaten Thread in der Lib, der dann normal beendet werden kann.

Die Sache ist, ich habe das gleiche Problem mit Threads, und aus diesem Grund kann ich nicht korrekt beenden andere Prozesse (Threads), die eine Reihe von Objekten, die zerstört werden müssen haben.
Ich kann andere Prozesse nicht korrekt beenden (d. h. ich kann andere Prozesse nicht beenden).
Das Terminal arbeitet fehlerhaft mit dem AusgabepunktDLL_PROCESS_DETACH.

Ich werde versuchen, was TheXpert vorgeschlagen, aber die Tatsache, dass das Terminal entlädt dll sofort, unabhängig von DLL_PROCESS_DETACH, muss es ein Fehler im Terminal sein.

TheXpert:

Die DLL wird nicht (notwendigerweise) sofort nach Beendigung des Dienstes entladen (ich könnte mich irren)

Wie auch immer, was Sie mit DLL_PROCESS_DETACH machen, ist zu spät. Erstellen Sie eine explizite Funktion deinit in der DLL, die dieses Flag setzt und beim Herunterfahren des Dienstes explizit aufgerufen wird.

Danke für den Hinweis, ich werde es auf diese Weise versuchen.

 
Roman:

Die Sache ist, ich habe das gleiche Problem mit Threads und deshalb kann ich nicht ordnungsgemäß beenden andere Prozesse (Threads), die eine Reihe von Objekten, die zerstört werden müssen haben.
Ich kann andere Prozesse nicht korrekt beenden (d.h. ich kann nichts gegen sie unternehmen).
Das Terminal arbeitet fehlerhaft mit dem Ausgabepunkt DLL_PROCESS_DETACH.

Ich werde versuchen, was TheXpert vorgeschlagen, aber Terminal entlädt dll auf einmal, unabhängig von DLL_PROCESS_DETACH, es muss ein Terminal-Bug sein.

Danke für den Tipp, ich werde es auf diese Weise versuchen.

Wie kommen Sie darauf, dass der dll in einem separaten Thread lebt? Sie haben einen trivialen Programmabsturz, der in Schleifenbedingungen nicht behandelt wird.

Und DllMain wird beim Verbinden/Trennen der DLL mit dem Prozess DLL_PROCESS und beim Erstellen/Beenden des in diesem Prozess erstellten Threads DLL_THREAD ausgeführt. Ihr bool Detach ist also nicht unbedingt in der dll vorhanden, weil der Compiler es im Rahmen der Optimierung entfernt haben könnte, denn bei der Ausführung aller Funktionen während der Lebensdauer der dll ändert es sich nicht und ist gleich false.

 
Vladimir Simakov:

Wie kommen Sie darauf, dass der dll in einem separaten Thread lebt? Sie haben einen trivialen Programmabsturz, der in Schleifenbedingungen nicht behandelt wird.

Und DllMain wird gestartet, wenn Sie die dll mit dem Prozess DLL_PROCESS verbinden/trennen und wenn Sie einen Thread erstellen/trennen, der in diesem Prozess DLL_THREAD erstellt wird. Ihr bool Detach ist also nicht unbedingt in der dll vorhanden, weil der Compiler es im Rahmen der Optimierung entfernt haben könnte, denn bei der Ausführung aller Funktionen während der Lebensdauer der dll ändert es sich nicht und ist gleich false.

Es wurde nirgendwo gesagt, dass der dll in einem separaten Thread lebt.
Wir kommunizieren mit Vict und wir verstehen einander )).
Ich verstehe, dass es ein Absturz ist, ich verstehe nicht, warum das Flag in DLL_PROCESS_DETACH nicht funktioniert, um die while-Schleife zu beenden.
Wie für DLL_THREAD, sie sind nicht verfügbar für mql überhaupt, es ist in diesem Artikel geschrieben, ich es überprüft und sie wirklich nicht funktionieren.
Aber mit VS Compiler als Option, könnte auch ein Trick sein.
Ich würde gerne Erklärungen von kompetenten Vertretern hören, anstatt zu raten ))

 
Roman:
Ich glaube, es gibt ein Problem mit der Deinitialisierung von dll in Services, helfen Sie zu verstehen.
Das Problem ist folgendes. Nach dem Drücken des Befehls "Stop" im Menü "Service" wartet das Terminal aus irgendeinem Grund nicht auf das Ende der Funktion Fn().
Es versucht, die Verbindung mit der DLL vorzeitig zu unterbrechen, wobei das Terminal aufgehängt wird oder vollständig abstürzt (geschlossen wird).
Obwohl am DllMain-Einstiegspunkt das Detach-Flag in DLL_PROCESS_DETACH eindeutig ein Flag zum Beenden der while-Schleife setzt.

Aber while hat keine Zeit, die Schleife rechtzeitig zu verlassen, um die nachfolgenden Funktionen auszuführen, nachdem alle anderen Prozesse zusätzlich abgeschlossen sind.
Und beenden Sie die Funktion Fn() selbst.
Die Funktion DestroyFunction(); dient in diesem Beispiel als Kontrolle.

Der Inhalt der DLL


Der Inhalt des Programms Service.
Eine zusätzliche Verzögerung durch _StopFlag ist nicht hilfreich.


Sie haben also nicht die Kontrolle über das Terminal zurückerhalten, sondern sind in einer "Endlosschleife" innerhalb der Fn in der DLL "hängen geblieben".
Von welcher Art von normaler Beendigung reden wir hier?

Wenn Sie ein solches Verhalten benötigen, dann sollten Sie innerhalb von Fn in DLL einen separaten Thread mit Schleife laufen lassen, der durch ein Flag gestoppt werden sollte, das in der separaten Funktion FnStop und bei DLL_PROCESS_DETACH gesetzt wird