E_OUTOFMEMORY bei mehrfachem CImage->Load/Save



  • Ich benutze CImage zur Anzeige von JPG-Bildern.
    Meine Routine LeseJPG wird pro Bilddatei im Directory aufgerufen.
    Mit wenig Dateien klappt es, aber bei etwa 20 Bildern kommt der o.G. Fehler.
    Sicherlich bleiben erhebliche Datenmengen im Speicher erhalten.
    Beim Debug im VS2017 sehe ich, dass der benutze Prozessspeicher bis auf ca. 2 TB anwächst, dann kommt der Abbruch.
    Sicherlich muss ich noch etwas für die Freigabe tun.
    Hier ein Auszug des Codes:

    BYTE * LeseJPG (char * szFileName)
    {
      BYTE *  lpPuBMP ; // Pointer auf BMP-Puffer im Speicher
      char *  szTempBMP = "C:\\Temp\\#TmpBMP#.bmp";
      CImage * image = new CImage;
    
      HRESULT hResult1 = image->Load(tFileName); // JPG-Datei einlesen
      HRESULT hResult2 = image->Save(szTempBMP); // #TmpBMP#.bmp ausgeben
    
      image->Detach();
      delete(image);
     
      lpPuBMP = LeseBMP(szTempBMP, TRUE); // #TmpBMP#.bmp in BMP-Puffer lesen
    
      DeleteFile(szTempBMP);  // #TmpBMP#.bmp wieder löschen
    
      return lpPuBMP ;  // Pointer auf BMP-Puffer im Speicher
    
    } // Ende LeseJPG```
    
    


  • Wo gibst du denn den Speicher für das zurückgegebene Byte-Array wieder frei?

    Warum hantierst du denn überhaupt mit so vielen Zeigern? Stichwörter: smart pointer, RAII.

    PS: Pfade wie "C:\Temp" solltest du vermeiden, diese gibt es nicht unbedingt auf jedem System. Besser: Creating and Using a Temporary File



  • @th69 ,
    Danke für Deine Antwort.
    C:\Temp nehme ich auch nicht, stattdessen hole ich %temp% aus den Umgebungsvariablen, ich wollte nur hier im Forum den Code möglichst kurz halten.
    Wenn Du lpPuBMP meinst, das wird später zurückgegeben.
    Es gibt eine Routinen, wie LeseJPG, LeseBMP, LeseGMX usw.
    Das Programm habe ich vor vielen Jahren mit C++ 6.0 erarbeitet. Damals habe ich JPG-Dateien mit den frei benutzbaren Routinen eingelesen, und das klappt bis heute noch

    • Copyright (C) 1991-1996, Thomas G. Lane.
    • This file is part of the Independent JPEG Group's software.

    Dazu muss ich aber das Programm mit C++6.0 umwandeln, was auch unter Windows 10 geht, die dabei entstehende EXE muss allerdings im Kompatibilitätsmodus für XP-SP3 ausgeführt werden.
    Unter Windows 8.1 und 7 funktioniert alles normal.

    Ich wollte das Programm zunächst einmal fehlerfrei mit VS2017 umwandeln. Da gab es mit den JPG-Sourcen unlösbare Probleme, deshalb habe ich sie entfernt.

    Ich habe einen wenig eleganten aber einfachen Trick benutzt, ich benutze CImage, lese damit die JPG ein und speichere sie als eine temporäre BMP-Datei. Die Routine LeseBMP gibt es im Programm, wenn ich 100 BMP-Dateien damit verarbeite, funktioniert alles problemlos.
    Auch mit den JPG-Dateien klappt es, nur, wenn es mehr als 18 sind, läuft der Speicher voll.
    Mit new Image wird Image angelegt und später mit delete Image wieder gelöscht.
    Wo CImage die mit image->load geladene JPG speichert und wie ich diesen Speicher freigeben kann, oder muss man das gar nicht ? - das ist meine Frage.

    Noch eine Zusatzfrage: wie muss ich den Code einklammern [CODE][/CODE] funktioniert leider nicht.



  • Alles was in CImage drin ist und der Speicher wird bei delete des Objektes wieder freigegeben?

    Warum machst Du überhaupt ein new auf das CImage. Du kannst doch direkt eine Instanz nehmen.
    Ich würde sagen, Du hast an anderer Stelle ein Speicherleck. Was passiert mit lpPuBMP?

    Code wird mit drei ``` eingeleitet und wieder beendet. Du hast einen Button dafür!



  • Das Detach hat da nichts verloren.



  • @caligulaminus sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    Das Detach hat da nichts verloren.

    Bingo! Das wird es sein. Habe ich überlesen.



  • @martin-richter sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    Warum machst Du überhaupt ein new auf das CImage. Du kannst doch direkt eine Instanz nehmen.

    Wie mache ich das mit "direkt eine Instanz nehmen" - ich kenne mich da nicht so aus.
    Die Variante mit new habe ich in einem Beispiel-Code gesehen.
    Detach habe ich rausgenommen. Der Fehler kommt trotzdem.



  • @hkdd sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    Wie mache ich das mit "direkt eine Instanz nehmen" - ich kenne mich da nicht so aus.

    CImage * image = new CImage;
    

    -->

    CImage image;


  • @swordfish, das wäre ja denkbar einfach, werde ich probieren.
    CImage kann ja neben ->Load und ->Save noch viele andere Dinge, wo Daten der BITMAP dem Rufer zur Verfügung gestellt werden. Die müssen ja irgendwo gespeichert sein. Mit welchem Aufruf teile ich CImage mit, dass nun alles erledigt ist und diese Daten aus dem Speicher entfernt werden können ?

    delete Image gehört ja zu new CImage.
    Wenn man kein new macht, gibt es auch kein delete.



  • @hkdd

    delete Image gehört ja zu new CImage.
    Wenn man kein new macht, gibt es auch kein delete.

    Lerne C++. Schon mal was von Destruktoren gehört? 👎
    Wenn CImage out of scope geht wird der Destruktor aufgerufen. (Automatisch)

    Aber schmeiss dieses dumme Detach raus.



  • @martin-richter und alle anderen !!!
    Jetzt klappt es.
    Die Ursache war doch, wie von Euch vermutet, die angeforderten Areas.
    Ich habe LeseJPG jetzt ganz einfach gemacht, es wird nur die JPG gelesen und als temporäre BMP Datei ausgeben. Mittels RCode wird angezeigt, ob das geklappt hat oder nicht.
    Die rufende Routine läßt dann die BMP weiterverarbeiten. Dabei geht hinsichtlich des Speichers alles seinen korrekten Gang.

    //  ##############################################
    //  ###                                        ###
    //  ###  JPG-Datei temporäre BMP kopieren      ###
    //  ###                                        ###
    //  ##############################################
    
    int LeseJPG (char * szFileName, BOOL qMitDaten)
    {
      CImage image;
        
      HRESULT hResult1 = image.Load(_T(szFileName)); // JPG-Datei einlesen
      if (hResult1 != S_OK) { return 1; } // Fehler beim LOAD JPG  
    
      HRESULT hResult2 = image.Save(szTmpJpgBmp);
      if (hResult2 != S_OK) { return 2; } // Fehler beim SAVE BMP
      
      return 0; // OK temporäre BMP aus JPG erstellt
    
    } // Ende LeseJPG```
     
    Der Aufruf sieht nun so aus:
    ```  case TypGIF:
               lpPuBmpPIC = LeseGIF (szFileName, TRUE) ; // GIF-Datei in BMP-Pu lesen
               break;
    
          case TypJPG:
              rcJPG1 = LeseJPG (szFileName, TRUE) ; // JPG-Datei in Temp-BMP kopieren
    	  if (rcJPG1 == 0)
    	  {
                 lpPuBmpPIC = LeseBMP(szTmpJpgBmp, TRUE); // temp. BMP-Datei in BMP-Pu lesen
    	     DeleteFile(szTmpJpgBmp);  // Temporäre BMP aus JPG löschen
    	  }
    	  else
    	  {
    	     lpPuBmpPIC = NULL;
    	  }
              break;
    

    DANKE !!! für Euere nette Unterstützung.



  • Hallo - noch ein Zusatz-Problem....
    Wenn ich das Programm mit VS2017 erstelle, dann läuft es unter Win7-32&64, 8.1-64 und 10-64 (meine Systeme), aber nicht mehr unter XP.
    Da kommt sofort ein kleines Fenster mit dem Hinweis:

    <Programmname>.exe ist keine zulässige Win32-Anwendung.

    Für XP muss ich also weiterhin die Programme mit VC98_6.0 erstellen.

    Ich erstelle auch viele meiner kleinen Programme mit Delphi7, die habe ich an die neue Umgebung RAD-Studio 10.0 Berlin angepasst. Die damit erstellen Programme funktionieren problemlos unter XP:

    Ich selbst habe zwar noch XP (zum Testen), nutze es aber kaum.
    Aber nahezu alle meine Ärzte mit spezieller Hardware, wie EKG, Nerventest beim Neurologen, auch bei der Notaufnahme im Krankenhaus laufen die PCs unter XP, das erkennt man sofort an der grünen START-Button links unten.

    Wahrscheinlich müssten die Praxen alle neue Hardware anschaffen, weil die vorhandenen Geräte keine Win10-tauglichen Treiber haben. Es geht also nicht nur um Win10 statt XP.

    Wenn man also für seinen Arzt ein kleines Helferlein machen möchte, dann sollte dieses auch unter XP laufen. Mich wundert, dass es mit VS2017 nicht geht, obwohl man damit ja nur Win32-Programme erstellen kann.

    Ich habe auch versucht, das Projekt mit VS2015 und VS2010 umzuwandeln, leider akzeptieren diese Programme keine Projekte von VS2017.
    CImage gibt es dort offenbar auch noch nicht.



  • @hkdd sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    Für XP muss ich also weiterhin die Programme mit VC98_6.0 erstellen.

    Hast Du neulich mal (vielleicht auch nur aus versehen?) auf einen Kalender geschaut?

    Configuring Programs for Windows XP



  • @swordfish
    auf dem Kalender habe ich keine Hinweise dazu entdeckt.
    Dein Link klingt vielversprechend.
    Ich nutze ja nur die Free-Variante von VS2017, mal sehen, ob man damit auch die erforderlichen Komponenten nachinstallieren kann.
    Ich hoffe nur, dass auch das richtige gemeint ist.
    Ich will nicht VS2017 unter XP laufen lassen, sondern nur die damit unter Win10 erstellten EXE-Programme.

    Bei Plattform steht Win32 (das ist mein XP auch).
    Als Zielplattform steht Windows (ohne Versionsangabe), also nicht iOS oder Android.



  • @hkdd sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    Ich nutze ja nur die Free-Variante von VS2017, mal sehen, ob man damit auch die erforderlichen Komponenten nachinstallieren kann.[/quote]

    Ja.

    @hkdd sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    Ich hoffe nur, dass auch das richtige gemeint ist.
    Ich will nicht VS2017 unter XP laufen lassen, sondern nur die damit unter Win10 erstellten EXE-Programme.

    Ja.

    @hkdd sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    Bei Plattform steht Win32 (das ist mein XP auch).

    Ja. Aber Programme, die mit einem Platform Toolset neuer als v140 (Visual Studio 2015) gebaut wurden, laufen auf XP trotzdem nicht.



  • @swordfish sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    Hast Du neulich mal (vielleicht auch nur aus versehen?) auf einen Kalender geschaut?

    Ich habe inzwischen einfachste Hello World Programme auch mit VS2015 und VS2010 gemacht, die laufen alle unter XP nicht.
    Lt. Kalender wurde der XP-Support am 08.04.2014 eingestellt.
    Da sollten doch Programme, die mit VS2010 kompiliert sind, unter XP funktionieren.

    Da bleibt als einziges Tool mit dem man Programme erstellen kann, die unter allen Windows-Versionen lauffähig sind => MS C++ 6.0
    Das funktioniert immer noch auch unter WIn10.



  • @hkdd sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    Ich habe inzwischen einfachste Hello World Programme auch mit VS2015 und VS2010 gemacht, die laufen alle unter XP nicht.

    Ist in den Projekteinstellungen auch wirklich das "Platform Toolset v140_xp" eingestellt? "laufen nicht" ist keine Fehlerbeschreibung. Was passiert genau unter welchen Umständen?

    @hkdd sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    Da bleibt als einziges Tool mit dem man Programme erstellen kann, die unter allen Windows-Versionen lauffähig sind => MS C++ 6.0

    Ich habe Dir doch oben einen Link zur Anleitung gegeben, damit es auch mit Visual Studio 2017 funktioniert!?



  • @swordfish
    Bei meiner VS-Version ist nur Win32 als Plattform einstellbar.
    Ich habe noch nicht gefunden, wie man hier im Forum ein Bild einfügen kann.



  • @hkdd sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    Bei meiner VS-Version

    Könntest Du Dir bitte angewöhnen, Dich etwas präziser auszudrücken um Nachfragen zu vermeiden? Welche Version von Visual Studio?

    @hkdd sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    ist nur Win32 als Plattform einstellbar.

    Ich kann es zwar nicht mit Sicherheit sagen, weil ich nicht weiß welche Version, aber "Project Settings" --> links im Baum: "General" --> rechts in der Liste: "Platform Toolset"

    @hkdd sagte in E_OUTOFMEMORY bei mehrfachem CImage->Load/Save:

    Ich habe noch nicht gefunden, wie man hier im Forum ein Bild einfügen kann.

    "Einfügen"? Garnicht. Ich kann mir zwar nicht vorstellen, wozu es gut sein sollte, aber wenn Du meinst: irgendwo hochladen und hier einen Link posten.



  • @swordfish,
    BILDER sagen manchmal mehr als Worte....

    Hier die Fehlermeldungen, wie sie unter XP zu sehen sind.
    http://www.hkressedd.de/bilder/xpVSerr.jpg

    Und hier die Plattform-Möglichkeiten
    http://www.hkressedd.de/bilder/10vs2010ALLG.jpg