エラー、バグ、質問 - ページ 2540

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

何がしたいんだ?

あなたやフェドセーエフなどのような無能な人が、コメントでバグやデザインの議論に参加しないように。

MQLでC++から丸ごと取り入れた構文や仕組みが、C++と同じように動作すること。

セルゲイ・タボリン

MQLがC++の完全なアナログになるためには?

戯言だとわかっていても、口に出さなければならない。
セルゲイ・タボリン

そして、そのことで泣き言を言ったり、鼻水を吹いたりするのはやめましょう。そのような「議論」のために別スレッドを開設しました。

言語が違うだのスレが違うだのウザいのはお前の方だろw

自分と同調者のために別スレを立てて、そこで愚痴ればいい。

 
端末でmqdファイルを解放させるには?いっそのこと、インターフェイスから削除する方法が社内にあればいいのですが。
 
Stanislav Korotky:
端末でmqdファイルを解放させるには?あるいは、さらに良いのは、インターフェイスから削除する方法が社内にあればいいのですが。

質問の内容は大体想像がつきます。言い直した方がいい。

 
ServicesのDLL deinitialisationに問題があると思うのですが、理解するのに役立ちます。
問題はこれだ。サービスメニューの「停止」コマンドを押した後、端末がなぜかFn()関数の終了を待たない。
早まってDLLとの接続を切ろうとし、端末をハングアップさせたり、完全にクラッシュ(終了)してしまうのです。
DllMainのエントリポイントでは、DLL_PROCESS_DETACHのDetachフラグが明示的にwhileループを終了させるフラグをセットしていますが、DLL_PROCESS_DETACHのDetachフラグが明示的にセットされていない場合、whileループが終了してしまいます。

しかし、whileは、他のすべての処理が追加的に完了した後、下の関数を実行する時間内にループを抜ける時間がない。
そして、Fn()関数そのものを終了させる。
この例では、DestroyFunction();関数がチェックとして機能します。

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;
}


プログラムサービスの内容
StopFlagによる追加遅延は役に立ちません。

//+------------------------------------------------------------------+
//|                                                      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);
}
//+------------------------------------------------------------------+
ファイル:
MQL5.zip  54 kb
 
Roman:
ServicesのDLLのdeinitialisationに問題があると思うのですが、助けてください。

サービス終了後、すぐにDLLがアンロードされるとは限らない(間違っているかもしれない

いずれにせよ、DLL_PROCESS_DETACHで行うことは遅すぎるのです。このフラグを設定する明示的なdeinit関数をDLLに作成し、サービス終了時に明示的に呼び出すようにする。

 
Roman:

ターミナルは、スレッドがstart()から戻った後、libのアンロードを開始するのだと思います。それ以外は、どのような仕組みになっているのでしょうか。プログラムが実行され、その環境を壊し始める?これはナンセンスだ。ループでスクリプトスレッドを追いかけるのではなく、libで別スレッドを立ち上げれば、正常に終了させることができるようになります。

 
Vict:

ターミナルは、スレッドがstart()から戻った後、libのアンロードを開始するのだと思います。そうでなければ、どのように機能するのでしょうか?プログラムが実行され、その環境を壊し始める?これはナンセンスだ。libで別スレッドを立ち上げれば、正常に終了させることができます。

つまり、スレッドについても同じ問題があり、このため、破壊する必要のあるオブジェクトを大量に持つ他のプロセス(スレッド)を正しく終了させることができないのです。
他のプロセスを正しく終了させることができない(他のプロセスをkillすることができない)。
出力ポイントDLL_PROCESS_DETACH で Terminal が正しく動作しない。

TheXpertの提案を試してみますが、DLL_PROCESS_DETACHに関係なく、ターミナルがすぐにdllをアンロードしてしまうということは、ターミナルのエラーなのでしょう。

TheXpert です。

サービス終了後、すぐにDLLがアンロードされるわけではない(間違っているかもしれない)。

とにかく、DLL_PROCESS_DETACHでやっていることは遅すぎです。このフラグを設定し、サービス停止時に明示的に呼び出す関数deinitをDLLに作成する。

ヒントありがとうございます、その方法でやってみます。

 
Roman:

スレッドにも同じ問題があり、そのせいで破壊しなければならないオブジェクトを大量に持っている他のプロセス(スレッド)を適切に終了させることができないことです。
他のプロセスを正しく終了させることができない(=何もできない)。
DLL_PROCESS_DETACH 出力ポイントを使用すると、Terminal が正しく動作しない。

TheXpertが提案したことを試してみますが、ターミナルはDLL_PROCESS_DETACHに関係なく、一度にDLLをアンロードします、ターミナルのバグでしょう。

ありがとうございます、その方法でやってみます。

なんでdllが別スレに住んでると思ってるんだ?ループ条件では処理されない些細なプログラムのクラッシュがあるのです。

また、DllMainは、DLL_PROCESSプロセスへのDLLの接続/切断時、およびこのプロセスで作成されたスレッドDLL_THREADの生成/終了時に実行されます。なぜなら、コンパイラが最適化の枠組みの中でそれを削除した可能性があり、DLLのライフタイム 中にすべての関数を実行しても、それは変化せず、falseに等しいからです。

 
Vladimir Simakov:

なんでdllが別スレに住んでると思ってるんだ?ループ条件では処理されない些細なプログラムのクラッシュがあるのです。

そして、DllMainは、DLL_PROCESSのプロセスにDLLを接続/切断したときと、このプロセスDLL_THREADに作られたスレッドを生成/切断したときに起動されます。なぜなら、コンパイラが最適化の枠組みの中でそれを削除した可能性があり、DLLのライフタイム 中にすべての関数を実行しても、それは変化せず、falseに等しいからです。

dllが別スレで生きてるなんてどこにも書いてないんだけど。
Victでコミュニケーションをとり、理解し合う ))。
クラッシュするのは理解できるのですが、DLL_PROCESS_DETACHのフラグでwhileループを抜けるのがうまくいかないのはなぜでしょう?
DLL_THREADに関しては、mqlでは全く使えません、この 記事に書いてあります、確認しましたが、本当に使えません。
しかし、VSコンパイラがオプションで付いているので、仕掛けもありそうです。
推測ではなく、有能な担当者の説明を聞きたい ))

 
Roman:
ServicesのDLLのdeinitialisationに問題があると思うのですが、理解の手助けをしてください。
問題はこれだ。サービスメニューの「停止」コマンドを押した後、端末がなぜかFn()関数の終了を待たない。
早まってDLLとの接続を切ろうとし、端末をハングアップさせたり、完全にクラッシュ(終了)してしまうのです。
DllMain のエントリポイントでは、DLL_PROCESS_DETACH の Detach フラグは明らかに while ループを終了させるフラグをセットしていますが、DLL_PROCESS_DETACH の Detach フラグは、DLL_PROCESS_DETACH の Detach フラグをセットしていません。

しかし、whileは、他のすべての処理が追加的に完了した後、下の関数を実行する時間内にループを抜ける時間がない。
そして、Fn()関数そのものを終了させる。
この例では、DestroyFunction();関数がチェックとして機能します。

dllの内容


プログラムサービスの内容
StopFlagによる追加遅延は役に立ちません。


つまり、端末に制御を戻さず、DLL内のFn内部で「無限」ループに「ハングアップ」してしまったのですね。
正常終了ってどんなんだよ!?

このような動作が必要な場合、DLL の Fn 内でループを持つ別のスレッドを実行し、別の関数 FnStop と DLL_PROCESS_DETACH で設定されるフラグによって停止させる必要があります。