質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework 4.0

Microsoft Windows用のソフトウェア開発環境/実行環境である .NET Frameworkの4番目のメジャーバージョンです。

Q&A

解決済

2回答

4236閲覧

C# DLL参照した呼び出し先で例外が発生することなく異常終了している

say5140

総合スコア12

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework 4.0

Microsoft Windows用のソフトウェア開発環境/実行環境である .NET Frameworkの4番目のメジャーバージョンです。

0グッド

2クリップ

投稿2017/12/20 15:11

編集2017/12/22 01:16

C#でコンソールアプリケーションからDLLファイルを参照し処理をするプログラムを開発しています。
DLLファイルの参照はプロジェクトの参照設定で行っており、DLLもC#で開発したものです。
呼び出し元、参照先DLLの構造は以下のようになっています。

※職場から書き込みできないため、大雑把なサンプルコードとなっており読みづらい部分があるかと思いますがご容赦ください。

C#

1//呼び出し元(コンソールアプリケーション) 2class Program 3{ 4 static void Main(string[] args) 5 { 6 try 7 { 8 int retCd = 0; 9 var hoge = new hogeClass(); //hogeClass.dllを参照設定 10 retCd = hoge.InitProcess(); 11 if(retCd != 0) 12 { 13 エラー判定で終了 14 } 15 16 retCd = hoge.ExecProcess(); 17 if(retCd != 0) 18 { 19 エラー判定で終了 20 } 21 } 22 catch(Exception e) 23 { 24 //エラー処理 25 リターンコード 99 26 } 27 } 28}

C#

1//hogeClass.dll側 2public class hogeClass 3{ 4 public int InitProcess() 5 { 6 try 7 { 8 処理1 9 処理2 10 処理3 11 処理4 12 処理5 13 14 リターンコード 100 15 } 16 catch(Exception e) 17 { 18 //エラー処理 19 リターンコード 109 20 } 21 } 22}

C#

1ファイルの削除(再帰呼び出し) 2 public static void DeleteOldLog(string dirPath, int limitSize) 3 { 4 if (!Directory.Exists(dirPath)) 5 { 6 return; 7 } 8 9 //現在のファイル容量を取得 10 var size = GetLogDirSize(dirPath); 11 if (size < limitSize) 12 { 13 return; 14 } 15 16 DirectoryInfo logDirInfo = new DirectoryInfo(dirPath); 17 var files = logDirInfo.EnumerateFiles("*", SearchOption.TopDirectoryOnly).ToArray(); 18 19 if (files.Length == 0) 20 { 21 return; 22 } 23 else 24 { 25 //ファイル日付の昇順でソート 26 var sortFiles = from file in files 27 orderby file.LastWriteTime 28 select file.FullName; 29 30 int dtLen = 14; //yyyyMMddHHmmss 31 32 //ファイル名のタイムスタンプを見つける 33 string timeStamp = string.Empty; 34 foreach (var file in sortFiles) 35 { 36 var fileName = Path.GetFileNameWithoutExtension(file); 37 if (fileName.Length >= dtLen) 38 { 39 //拡張子より前14ケタを取得 40 var stIndex = fileName.Length - dtLen; //開始インデックス 41 timeStamp = fileName.Substring(stIndex, dtLen); 42 43 //日付形式か 44 if (IsDateTime(timeStamp)) 45 { 46 //日付形式であれば採用 47 break; 48 } 49 else 50 { 51 timeStamp = string.Empty; 52 } 53 } 54 } 55 56 //該当なしの場合 57 if (timeStamp.Length == 0) 58 { 59 return; 60 } 61 62 //タイムスタンプでファイル検索 63 var search = "*" + timeStamp + "*"; 64 var delFiles = logDirInfo.EnumerateFiles(search, SearchOption.TopDirectoryOnly).ToArray(); 65 foreach (var file in delFiles) 66 { 67 //ファイル削除 68 File.Delete(file.FullName); 69 } 70 71 //再帰実行し最大容量を下回るまで繰り返す 72 DeleteOldLog(dirPath, limitSize); 73 } 74 }

呼び出し側の例外時のStackTrace
オブジェクト参照がオブジェクト インスタンスに設定されていません。
場所 xxxx.InitProcess()
場所 呼び出し側の関数名

現在、コンソールアプリケーション側で例外をキャッチし、リターンコード99で終了しています。
メッセージは「オブジェクト参照がオブジェクト インスタンスに設定されていません。」です。
そのため、インスタンス作成がうまくできていないと思っていたのですが、DLL側に調査用のログ出力を
追加して調べたところ、Dllの呼び出し(InitProcess関数)は呼び出せていました。
しかし、ログが処理3までしか出力されておらず、その後Exceptionも発生することなく、呼び出し元に戻り
catchされているとわかりました。

DLL側でtry、catchしているため、例外が発生した場合上記のサンプルでリターンコード109が返るはず
なのですが、DLL側ではcatchされず、コンソール側でcatchされています。

このように、処理の途中でインスタンスが消えてしまう(?)ことがあるのでしょうか。
調査しようにも方法に困っています。
UnhandledExceptionイベントを追加してみましたが、イベントに入ってきていないようでした。

ちなみにログに出力された処理3以降の処理では、古いログファイルの削除処理を行っています。
ファイル削除用の関数を呼び出し、ログ出力フォルダのサイズが指定されたサイズ以下になるまで再帰的に
この関数を呼び出すようになっています。またこのコンソールアプリケーションは運用上多重実行されるため、
削除するログファイルがタイミングによっては競合する場合もあるため、この関数に問題があるのではとも
思っています。
ただ再現性も低く、DLL側でExceptionも発生しない状況のため、対策に困っております。

何かアドバイスを頂けたら嬉しいです。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ebiryo

2017/12/21 03:45

Main側でCatchしたExceptionのStackTraceはどうなっていますか?
YAmaGNZ

2017/12/21 03:52

提示されたコードだとInitProcessのリターン値が0になることはなく、呼び出し側で正常終了判断されることはないのでは?コードを載せるのであれば、現象が確認できるコードを載せるべきだと思います。
guest

回答2

0

ベストアンサー

DLL側ではcatchされず、コンソール側でcatchされています。

これは間違いだと思います。
InitProcess はコンストラクタから呼び出されているのではないですか?
それが失敗しているのでコンストラクタも失敗し、結果として呼び出し側で例外が起こっているのでは?

どちらにせよ処理 3 まで動いているということは処理 4 に問題があることは明らかです。

つまり、ここに載っているコードではなく、あなたが省略されたところに問題があります。

問題がないコードではなく、問題があるコードを載せてください。

投稿2017/12/21 00:41

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

say5140

2017/12/23 00:53

ログの削除処理で再帰的に呼び出している部分を見直し、同時実行中の他のプロセスとファイルが競合しないようにしました。 もともと再現性が低くなかなか確認できなかったのですが、プログラム見直し後は今のところ現象が発生していません。 ログに出力されていた通り、処理3以降に問題ありということで、冷静に考えればその通りですね。 少し周りが見えなくなっていました。 ありがとうございました。
guest

0

こんにちは。

ご提示されている内容は、不可思議な現象が起きているように見えますね。
そのような時は何かの前提条件を間違っていることも少なくありません。
私がよくやらかすのはログの取り損ないです。ログをファイルへ出力し、書き込みキャッシュが効いてしまってプログラムは出力しているけどファイルへ書き込まれる前に落ちてしまい、ログに残らないことです。

処理4以降のログがでていないように見えて、実はでているけどキャッシュまででファイルに落ちていないような現象です。
この場合は、実はInitProcessでは例外は発生してなくて、ExecProcessで例外が発生している可能性があります。

投稿2017/12/21 03:39

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

say5140

2017/12/23 00:54

そういうこともあるのですね。 今後、解析する際は気を付けたいと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問