Serialisierung (BinaryFormatter) OutOfMemory Exception

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Eistee.

    Serialisierung (BinaryFormatter) OutOfMemory Exception

    Hi,

    wollte mal Fragen was Ihr alles so für Ursachen kennt, die während der Deserialisierung
    zu einer OutOfMemory Exception führen können, außer das einem der Speicher ausgeht.
    Die zu lesende Datei ist ~ 500KB groß.
    Ringverweise? So was:

    VB.NET-Quellcode

    1. Class Ringverweis
    2. Public Property Objekt As Object
    3. End Class
    4. Dim rv1 As New Ringverweis, rv2 As New Ringverweis
    5. rv1.Objekt = rv2
    6. rv2.Objekt = rv1

    Auf dem ersten Blick sieht es nicht sehr wahrscheinlich aus, dass etwas in dieser Art passiert, jedoch kann es vor allem bei größeren Programm durchaus auftreten.
    Es könnte allerdings sein, dass der BinaryFormatter darauf achtet.
    Habe eben gegoogelt, scheint ein Bug zu sein.

    Das hier hilft dir vielleicht: stackoverflow.com/questions/12…tion-during-serialization
    Ah ich bekomm es einfach nicht gelöst, hier mal der Komplette Code:

    Daten Klasse

    VB.NET-Quellcode

    1. <Serializable()> Public Class SerialData
    2. Public m_Level As Integer
    3. Public m_Level_Title As String
    4. Public m_Level_Description As String
    5. Public m_GameOver_Text As String
    6. '--------------------------------
    7. Public m_BackgroundData As String
    8. Public m_Layer1Data As String
    9. Public m_Layer2Data As String
    10. Public m_Layer3Data As String
    11. End Class



    Speichern Es werden alle Variabeln gefüllt.

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    2. Dim SerialData As New SerialData
    3. SerialData.m_Level = CInt(Me.CB_Level.Text)
    4. SerialData.m_Level_Title = tb_Kurzbeschreibung.Text
    5. SerialData.m_Level_Description = tb_Beschreibung.Text
    6. SerialData.m_GameOver_Text = tb_Gameover_Text.Text
    7. SerialData.m_BackgroundData = cb_Background_Textur.Text
    8. SerialData.m_Layer1Data = cb_Layer1_Textur.Text
    9. SerialData.m_Layer2Data = cb_Layer2_Textur.Text
    10. SerialData.m_Layer3Data = cb_Layer3_Textur.Text
    11. Dim bf As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
    12. Dim fs As New System.IO.FileStream(TextboxOutputPath.Text & "\Content\" & CB_Level.Text & ".bin", System.IO.FileMode.OpenOrCreate)
    13. bf.Serialize(fs, SerialData)
    14. fs.Close()
    15. fs.Dispose()
    16. End Sub



    Laden

    VB.NET-Quellcode

    1. Pfad = System.IO.Directory.GetCurrentDirectory & "\Content\" & ToLoad & ".bin"
    2. Dim fs As New System.IO.FileStream(Pfad, System.IO.FileMode.OpenOrCreate)
    3. Dim SerialData As New SerialData
    4. SerialData = DirectCast(Me.game.BinaryFormatter.Deserialize(fs), SerialData) ' OutOfMemory Exception!
    5. fs.Close()
    6. fs.Dispose()


    - Die Pfade müssen nicht wirklich Sinn ergeben, da die Datei eh von Hand verschoben wird.
    - Die Klasse "SerialData" ist in beiden Projekten absolut identisch!
    - Zudem passe ich den AssamblyNamen (von Hand mit MS Wordpad) an, da das Speichern in einem anderen Projetk geschied als das Laden.
    (Wenn ich dies nicht mache, gibt es einen "Assambly nicht gefunden Fehler", Da beim lesen ein anderer Assambly Name erwartet wird).

    Hoffe jemand erkennt vielleicht anhand des Codes einen Fehler.
    Oder sonst irgendwie ^^

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „Eistee“ ()

    @ErfinderDesRades:

    Objectbrowser schrieb:

    Gibt an, dass das Betriebssystem eine Datei öffnen soll, sofern diese vorhanden ist, oder andernfalls eine neue Datei erstellen soll & Der Abschitt über den Dateizugriff

    Da die Datei immer vorhanden ist, habe ich die Zeile jetzt mal in .Open geändert und noch den Zugriff zum lesen übergeben:

    VB.NET-Quellcode

    1. Dim fs As New System.IO.FileStream(Pfad, System.IO.FileMode.Open, IO.FileAccess.Read)


    Am Endergebnis hat sich nichts geändert.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Eistee“ ()

    Das war es! Es ist läuft zwar nocht nicht wie es sollte aber endlich bin ich den Memory fehler los Danke @ErfinderDesRades:.
    Durch das OpenOrCreate wurde nie eine neue Datei erstellt sondern nur eine Fehlerhafte bearbeitet.

    Der neue Fehler lautet:
    Der Eingabestream hat kein gültiges binäres Format. Die Startinhalte (in Bytes) sind: 20-01-20-20-20-FF-FF-FF-FF-01-20-20-20-20-20-20-20 ...

    Dieser entsteht wohl weil ich den Assambly Name mit Notepad von Hand ändere!
    Der Fix für den fehler findet man einen beitrag unter dem Hier 8-)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Eistee“ ()

    komisch.
    ich kann den Fehler nicht reproduzieren, und die PeterPunkt-Klasse verändert auch garnix an den Typnamen.
    Da sie keine Veränderung vornimmt kann sie auch weggelassen werden.

    Aber liegt vmtl. daran, dassich den Fehler nicht reproduzieren kann.

    Wie erzeugt man diesen Fehler?
    @ErfinderDesRades:

    Serialisiere eine belibiege Klasse mit z. B. einem String. Diese Klasse liegt in Projekt1
    Nun liest Du die Serialisierte Klasse in Projekt2 ein.

    Die folge wird ein "Assambly Name" Fehler sein.

    In der .bin heißt es: Projekt1.DEINEKLASSE
    Und beim lesen wird erwartet: Projekt2.DEINEKLASSE
    jo, das ist doch Humbug.
    Wenn du eine Datenklasse hast, die du zw verschiedenen Projekten herumschicken willst, dann musstedie in eine eigene Dll kompilieren, und diese Dll in beiden Projekten einbinden.

    Keinesfalls sollteste dieselbe Datenklasse in beiden Projekten als Code vorliegen haben, denn WinApplication1.MyDataClass ist etwas ganz anneres als WinApplication2.MyDataClass - auch wenn der Code 100% identisch ist.

    PeterPunkts "Lösung" ist also ein total fragwürdiger Hack - ein Workaround für Leute, die noch nicht vernünftig mit Dll-Projekten umgehen können, und die Serialisierung noch nicht ganz geschnackelt haben.
    Verdammt, so lange damit rumgeschlagen und jetzt kommt mir das mit der .dll so bekannt vor :cursing:
    Ich hab das irgendwo mal überflogen und wohl für unwichtig gehalten, ärgerlich.

    Ich habe gerade nochmal im MS Entwicklerbuch nachgeschlagen und die Methode welche von PeterPunkt genutzt wird, wurde dafür entwickelt um Probleme mit verschiedener Versionen eines Projektes zu behandeln:

    Nun erweitern Sie durch ein Update Ihr Programm, und es kommen einige Eigenschaften zur Datenklasse
    hinzu. Da sich die Deserialisierungsfunktionen beider Serialisierungsklassen am Objekt orientieren, erwartet
    es die Daten zu einigen Eigenschaften, die es im alten Objektmodell natürlich nicht gegeben hat. Der
    Deserialisierungsversuch schlägt in diesem Fall mit einer Ausnahme fehl.

    Eine Möglichkeit, das zu verhindern, besteht durch den Einsatz der so genannten SerializationBinder-
    Klasse, die für die Lösung des Versionsproblems konzipiert wurde.


    Ich werde jetzt mal versuchen alles in eine .dll zu schieben.