10

C# で作業しているアドオン内に 2 つの異なる関数があります。最近 (どうやら) Solidworks は、これら 2 つの関数の特定の部分に到達するとクラッシュするようになりました (それ以上の可能性もありますが、これまでに発生したのはこれら 2 つだけです)。デバッグ中、両方の関数で「メモリ アクセス違反」が発生します。エラー"。このエラーは、アクティブなドキュメントを閉じている行で毎回発生し、約 95% の確率で発生します。

ほとんどの場合、同じ部分にあります。実行時間や、開閉されたパーツの数とは無関係のようです。ファイルを閉じないと、エラーが発生しないようです。しかし、大規模なアセンブリを実行すると、それ自体の問題が生じます。閉じる前に 1 秒の待機を追加すると、エラーの頻度が減少するようです (同様に、エラーなしでアセンブリ全体を通過できる場合もあります)。

私が主に関心を持っている機能が何をしているのかを簡単に説明します。アセンブリのトップ レベルから機能し、カスタム プロパティをメイン アセンブリとサブアセンブリからそれらの子に伝達します。そのため、さまざまなアセンブリ ファイルやパーツ ファイルを頻繁に開いたり閉じたりしています。

以下のコードは、エラーを再現する最小限のコードにまで簡略化されています。エラーは 59 行目で発生します。これまでにオンラインで見たものから、これらを突き止めるのは難しいようです。どんな助けでも大歓迎です。

    public void propagateProps(bool overwrite)  
    {  
        List<string> assemblies = new List<string>();  
        string topAssem;  
        string compName = "";  
        int i = 0;  
        int j = 0;  
        int errors = 0, warnings = 0;  
        int partType = 1;  
        swModel = iSwApp.ActiveDoc;  
        if (swModel == null)  
        {  
            MessageBox.Show("No assembly document open. Please open an assembly and try again.", "Avengers Assemble Error");  
            return;  
        }  
        if (swModel.GetType() != 2)  
        {  
            MessageBox.Show("No assembly document open. Please open an assembly and try again.", "Avengers Assemble Error.");  
            return;  
        }  
        topAssem = swModel.GetPathName();  
        assemblies.Add(swModel.GetPathName());  
        swAssy = iSwApp.ActiveDoc;  
        while (i < assemblies.Count)  
        {  
            List<string> beenDone = new List<string>();  
            iSwApp.OpenDoc(assemblies[i], 2);  
            swModel = iSwApp.ActivateDoc(assemblies[i]);                  
            swAssy = iSwApp.ActiveDoc;  
            foreach (Component2 swComp in swAssy.GetComponents(true))  
            {  
                partType = 1;  
                compName = swComp.GetPathName();  
                if (compName.IndexOf(").SLD") > 0 || compName.IndexOf("REF") > 0)  
                {  
                    continue;  
                }  
                if (Path.GetExtension(compName).ToUpper() == ".SLDASM")  
                {  
                    partType = 2;  
                    assemblies.Add(compName);  
                }  
                iSwApp.OpenDoc(compName, partType);  
                swModel = iSwApp.ActivateDoc(compName);  
                if (swModel == null)  
                {  
                    continue;  
                }  


                #region things that might not be in  


            #endregion  


                boolstatus = swModel.Save3(5, errors, warnings);  
                System.Threading.Thread.Sleep(500);  
                iSwApp.CloseDoc(swModel.GetPathName());  
            swPart = null;  
            swModel = null;  
            }  
            ++i;  
            System.Threading.Thread.Sleep(500);  
        }  


        return;  
    }  

更新:この質問を見た後。メモリ アクセス違反の原因は何ですか? 関数で使用するいくつかのグローバル変数をいじってみましたが、効果がありませんでした。ただし、この問題を回避していると思われる部分をループするために、重要なコードを別の論理構造にラップすることができました。しかし、それはせいぜいバンドエイドだと感じており、将来この問題を回避できるようにしたいと考えています.

4

1 に答える 1

5

C# でコードを書いている - PInvokes、安全でないブロックなどを扱っていない限り、メモリ アクセス例外を発生させることは不可能です。唯一の合理的な答えは、SolidWorks にはバグがあり、妥当な入力が与えられた場合にクラッシュするか、妥当でない入力を検証していないためにクラッシュするということです。

本当の修正は、SolidWorks に連絡して、バグを再現して修正してもらうことです。それがなければ、コードを分析して、バグや障害の一般的なトリガーとなる相互作用を探すことができます。たとえば、すべての入力を正しく検証していない可能性があります。無効な値を指定して、黙って受け入れている可能性があります。それはずっと後まで壊れません。

誤って null を渡し、チェックしていなかった場合、後でその null からポインターを取得しようとすると、メモリ アクセス違反が発生する可能性があります。閉じた後にリソースを使用していて、そのような状態を検証していなかった場合、内部で古いポインターが使用され、メモリ アクセス違反が発生する可能性があります。

他の状況では、非同期操作が障害の原因である可能性があります。非同期操作を開始してから、その操作に関連付けられているリソースを閉じると、その操作が後でバックグラウンドで進行したときに、障害が発生する可能性があります。

返されたハンドルの使用方法が原因で、メモリ アクセス違反が発生している可能性があります。OpenDocからの戻り値を使用せず、代わりに他の方法でドキュメントにアクセスしようとしていることに気付きました。からの戻り値OpenDocがガベージ コレクションされるとどうなりますか? おそらく、SolidWorks は適切に参照カウントを行っていないため、戻り値が GC されると、ボンネットの下のハンドルが閉じられて null になります。さらに、他の操作はそれが有効であることを期待しているため、メモリアクセス違反が発生します。

非推奨の API を使用している可能性もあります。その場合、SolidWorks でコードを実行している可能性があります。これは、テストやメンテナンスが行われなくなったため、バグの可能性が高くなります。OpenDocドキュメントに非推奨としてリストされているメソッドを呼び出していることに気付きました。などの推奨される方法を代わりに使用することを検討してくださいOpenDoc6

API が壊れているか、壊れた入力に対して十分に検証されていないという実際の問題を修正する以外に、唯一の選択肢は、これらの一般的な API 問題の原因を調査することです。

于 2016-07-11T15:46:47.590 に答える