2011-11-14 7 views
1

私のクラッシュ報告システムは、例外が処理されていない例外ハンドラに到達し、これを発生させたコードを調べると、これがどうなっているのかわかりません。コードは完全に同期しており、try/catch 。どの胴体がすべてを捕まえるか(catch(Exception ex))は本当にすべてを捕らえないのですか?

明確化:このコードは、Windows Phone 7の上で実行されていると例外が制御されていない環境(つまり、ユーザーのデバイス上]での生産で起こっている

は、ここでは、コードです:

private void LoadUserData() 
{ 
    try 
    { 
     UserData = UserData.Deserialize(UserDataFileName, true); 

     // We succeeded. Backup the file, if possible. 
     if (IsoFile.Store.FileExists(UserDataFileName)) 
     { 
      try 
      { 
       IsoFile.CopyFile(UserDataFileName, UserDataFileBackupName); 
      } 
      catch (Exception ex) 
      { 
       EventManager.Current.ShipAssert("LoadUserData.Backup", ex); 
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     string currentFile = ""; 
     try 
     { 
      currentFile = IsoFile.ReadAllLines(UserDataFileName); 
     } 
     catch (Exception exInner) 
     { 
      currentFile = "Exception when trying to read file: " + exInner.ToString(); 
     } 
    } 
} 

そして、これはUserData.Deserialize(それはテンプレートベースクラスからです)のためのコードである

System.InvalidOperationException: There is an error in XML document (129, 54). ---> System.InvalidOperationException: There is an error in XML document (129, 54). ---> System.Xml.XmlException: Unexpected end of file has occurred. The following elements are not closed: value, item, VotedUrls, UserData. Line 129, position 54. at  
System.Xml.XmlTextReaderImpl.Throw(Exception e) at  
System.Xml.XmlTextReaderImpl.Throw(Int32 res, String resString, String arg) at  
System.Xml.XmlTextReaderImpl.Throw(Int32 pos, Int32 res, String resString, String arg) at  
System.Xml.XmlTextReaderImpl.ThrowUnclosedElements() at  
System.Xml.XmlTextReaderImpl.ParseElementContent() at  
System.Xml.XmlTextReaderImpl.Read() at  
System.Xml.XmlTextReader.Read() at  
System.Xml.XmlReader.ReadEndElement() at  
System.Xml.Serialization.XmlSerializationReader.DeserializePrimitiveElement(LogicalType deserializeAs, Accessor accessor, Fixup fixup, Object fixupTarget, String identifier, Boolean emptyValue, Boolean nullValue) at  
System.Xml.Serialization.XmlSerializationReader.deserializeElement(Accessor accessor, Fixup fixup, Object fixupTarget) at  
System.Xml.Serialization.XmlSerializationReader.DeserializeElement(Accessor accessor, Fixup fixup) at  
System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle) at  
SocialEbola.Shared.Utils.SerializableDictionary`2.ReadXml(XmlReader reader) at  
System.Xml.Serialization.XmlSerializationReader.DeserializeSerializableElement(LogicalType deserializeAs, Accessor accessor, Fixup fixup, Object fixupTarget, String identifier, Boolean emptyValue, Boolean nullValue) at  
System.Xml.Serialization.XmlSerializationReader.deserializeElement(Accessor accessor, Fixup fixup, Object fixupTarget) at  
System.Xml.Serialization.XmlSerializationReader.DeserializeElementMember(MemberValueCollection members, Object fixupTarget, Hashtable internalState, Boolean& firstElement) at  
System.Xml.Serialization.XmlSerializationReader.deserializeMembers(MemberValueCollection members, Object fixupTarget) at  
System.Xml.Serialization.XmlSerializationReader.DeserializeComplexElement(LogicalType deserializeAs, Accessor accessor, Fixup fixup, Object fixupTarget, String identifier, Boolean emptyValue, Boolean nullValue) at  
System.Xml.Serialization.XmlSerializationReader.deserializeElement(Accessor accessor, Fixup fixup, Object fixupTarget) at  
System.Xml.Serialization.XmlSerializationReader.DeserializeElement(Accessor accessor, Fixup fixup) at  
System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle) at  
System.Xml.Serialization.XmlSerializer.Deserialize(Stream stream) at  
SocialEbola.Lib.Serialization.SerializeHelper`1.Deserialize(Stream stream) at  
SocialEbola.Lib.Serialization.SerializeHelper`1.Deserialize(String file, Boolean createNew) at  
Fails.App.LoadUserData() at  
Fails.App.Application_Launching(Object sender, LaunchingEventArgs e) at  
Microsoft.Phone.Shell.PhoneApplicationService.FireLaunching() at  
Microsoft.Phone.Execution.NativeEmInterop.FireOnLaunching()  at  
System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle) at  
SocialEbola.Shared.Utils.SerializableDictionary`2.ReadXml(XmlReader reader) at  
System.Xml.Serialization.XmlSerializationReader.DeserializeSerializableElement(LogicalType deserializeAs, Accessor accessor, Fixup fixup, Object fixupTarget, String identifier, Boolean emptyValue, Boolean nullValue) at  
System.Xml.Serialization.XmlSerializationReader.deserializeElement(Accessor accessor, Fixup fixup, Object fixupTarget) at  
System.Xml.Serialization.XmlSerializationReader.DeserializeElementMember(MemberValueCollection members, Object fixupTarget, Hashtable internalState, Boolean& firstElement) at  
System.Xml.Serialization.XmlSerializationReader.deserializeMembers(MemberValueCollection members, Object fixupTarget) at  
System.Xml.Serialization.XmlSerializationReader.D 

:未処理の例外ハンドラに到達例外

public static T Deserialize(string file, bool createNew) 
{ 
    IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication(); 
    T result; 

    if (!store.FileExists(file)) 
    { 
     if (createNew) 
     { 
      result = new T(); 
     } 
     else 
     { 
      result = default(T); 
     } 
    } 
    else 
    { 
     using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(file, FileMode.Open, store)) 
     { 
      result = Deserialize(stream); 
     } 
    } 

    return result; 
} 

public static T Deserialize(Stream stream) 
{ 
    T t = (T)Serializer.Deserialize(stream); 
    return t; 
} 

シリアライザは次のように基底クラスで定義されています

public static XmlSerializer Serializer = new XmlSerializer(typeof(T)); 
+0

+1 SocialEbola。私は社会的なウイルスが大好きです。 –

+3

'UserData.Deserialize'メソッドを表示できますか?例外をスローする非同期処理を行うかもしれません。 –

+0

@Shahar Prish貼り付けたコードからスタックトラックが発生していませんか? Visual Studioまたはスタンドアローンで実行していますか? – wal

答えて

1

更新:私が最初にしようとすると、プロジェクトをクリーニングし、再構築されます。実行していると思うコードを実行していない可能性があります。そのdoesntのは、それを修正する場合(行番号を持っているdoesntのそのスタックは、最新のコンパイル済みのアセンブリではないかもしれないIE)

は今、あなたのUnhandledException方法ハンドラにブレークポイントを入れて、呼び出し元のスレッドがあるかどうかを判断

で読みます2つのスレッドIDのが異なる場合

private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 
{ 
    //add this line and put a breakpoint here. 
    var threadId = System.Threading.Thread.CurrentThread.ManagedThreadId; 
    Log.Error("CurrentDomain_UnhandledException", e.ExceptionObject as Exception); 
} 

はその後、それはあなたが見るの行動を説明することができます。例外がスローされたスレッドと同じ。 (@Ernoが記載されているように)

もしそれらが同じであれば、それが捕捉されているかどうかを確認するために、Deserializeへの呼び出しの前に、コードとして明示的な例外をスローします。例:

throw new Exception("test"); 
UserData = UserData.Deserialize(UserDataFileName, true); 

次に報告します。

+0

ありがとうございます。上の例では、この例外はユーザーデバイス上のプロダクションでのみ発生しています。ローカルのエミュレータ/マシンでこれを再現することはできませんので、すべて試すことはできません。コールスタックはこれらのデバイスから報告されます(したがって、デバッガがどのように結果を得ているかはわかりません)。返信いただきありがとうございます。 –

+0

@Shaharあなたのコードはそのように見える*その例外をキャッチする必要がありますので、私は方向を変更し、あなたが見ているコードが本番で同じバージョンであるかどうか尋ねますか?コードがソースのようなtry catchブロックを持っていることを確認するために、プロダクションDLLを逆コンパイルするためにリフレクタを使用するのが不明な場合。 – wal

+0

私はかなり確かですが、それは悪い考えではありません。私は見てみましょう。 –

1

.Net 2.0では、StackOverflowExceptionは取得できません。これはあなたのコードによって容易にトリップされる可能性のあるものです。 uncatchable以外の唯一の例外は、.Net 4.0のAccessViolationExceptionです。これは、保護されたメモリを読み取ろうとしている場合にのみ発生します。

私は、おそらくStackOverflowExceptionが疑わしいと思います。コードで再帰関数がないか調べ、デバッガをステップ実行してどのような条件が原因であるかを確認してください。

+0

スタックにInvalidOperationExceptionが表示されている場合、どのようにその結論に至りますか? – wal

+0

@ブライアンニッケル:私は何かが紛失しているかもしれませんが、ウォール氏のように、プロセスは失敗しませんでした。実際には、未処理の例外ハンドラを実行するという問題がありました。ありがとう。 –

+0

@Brian、例外処理がStackOverflowExceptionで終了することは間違いありません。例外処理は、例外タイプと一致するキャッチブロックと実行される必要があるfinallyブロックを探してコールスタックを処理するためです。スタックがエラー状態にある場合、その処理は実行できません。ただし、スタックオーバーフロー例外は、コールスタック上の深い再帰または非常に大きな量またはサイズの値型のために発生する可能性があります。示されたコードから、私はそれらの問題を示唆する何も表示されません。私は問題が他のところにあると思う。 –

0

私はいくつかの賛美歌を処理するベストプラクティスを学び、適用することをお勧めします。

フロー制御に例外を使用しないでください(実行中)、エラー状態を報告して処理するために使用しないでください。

キャッチブロックは、エラー状態から部分的にまたは完全に回復し、潜在的に例外を再スローするか、新しい(おそらくより詳細な例外をスローする)必要があります。ビジネスロジックをcatchブロックに入れないでください(実行中)。そうすることで、1つの例外を別のマスクにマスクすることができます。

(少なくとも部分的に)リカバリしようとしている例外をキャッチするか、より特定の例外をスローするためにのみ例外をキャッチします。例外は型によってキャッチされるので、これは実質的にSystem.Exceptionを捕まえるべきではないことを意味します:あなたが回復するのはあまりにも一般的です。

同様に、System.Exceptionなどの一般的ではない例外をスローしないでください。 .Net Frameworkクラスライブラリですでに定義されている例外を調べるか、System.Exceptionから直接的または間接的に派生する特定の例外タイプを作成します。

特定のtryブロックのcatchブロックが順番に評価されるため、より少ない派生例外タイプのブロックをcatchする前に、より多くの派生例外タイプのcatchブロックを配置するようにしてください。

適切なC#プログラミングリファレンスでは、例外のスローやキャッチに関する正しい使い方とベストプラクティスに関するガイダンスを提供する必要があります。

これを念頭に置いて - 14行目にはどのような例外タイプが検出されていますか?それを明示的にする。 - 16行目のコードで例外がスローされる可能性はありますか?その場合は、どのような例外処理が行われますか? - 22行目で宣言された変数がcatchブロックにスコープされているのはなぜですか?その直後に範囲外になることを考えれば、29行目にそれを割り当てる価値は何ですか?

あなたのコードでこれらのものを並べ替え、デバッガでステップ実行すれば、すぐに犯人を見つけたと思います。

+0

101のおかげで:)あなたの答えを明確にするためのいくつかの質問は、私はそれにもっとよく答えることができます... "フロー制御の例外を使用しないでください"とはどういう意味ですか?私はここで流れ制御とは何ですか?実行中のXMLファイルの妥当性をチェックする方法はありません。これを行う唯一の方法は、parseメソッドを呼び出すことです。失敗した場合、XMLに間違ったことが起こり、解析できません。あなたは私のspeicifcケースをどのように扱うことを提案しますか? –

+0

それは良い質問です。 LoadUserDataの最も外側のキャッチブロックの内側には、最外のtryブロックに例外がスローされた場合にのみ実行されるロジックがあります。フロー制御 - どのステートメントがどの状況下で実行されるかを指示します。代わりにcatchブロックを排他的に使用して例外からの復旧、ログの記録、ある例外タイプの別の例外への変換。 C#のフロー制御文には、if-then、foreachなどがあります。フロー制御構造でできることを行うために例外処理を使用しないでください。 –

+0

Gotcha。だからあなたが話している問題は、catch()がcatchの中でtrueに "errorOccurred"というローカル変数を設定した後で、catchから外されたロジックを含んでいるという事実です。私はこれについて正しいと思いますか?もしそうなら、私はあなたが言っていることを理解しています - 良い点。しかし、私が持っている問題はその前にあります。catch(Exception ex)はすべてのExceptionsをキャッチしていません。つまり、コードの再エンジニアリングによって解決されない、より基本的な問題がここにあります。正しい例外処理。 –

関連する問題