Arbeiten mit Pointern: Windows -> Funktioniert ; Linux (gleicher Code!!) -> Segmentation Fault.. Wo ist der Unters



  • Hallo ­čÖé

    Ich hab grad ein kleines Problem.. Um genau zu sein hab ich unter Windows eine Klasse geschrieben und wollte diese jetzt unter Linux nutzen.

    Das Problem: Ein und derselbe Code funktioniert unter Windows aber gibt unter Linux eine "Segmentation fault"..

    Hier die relevanten Codezeilen (damit kopiere ich ein Teilbild einer .bmp im Speicher, ich habs hier aber aufs n├Âtigste gek├╝rzt):

    [....]
    
    int newDataSize   = (height)*(width*3+newAdd); // die gr├Â├če des Teilbilds im Speicher ausrechnen
    BYTE** newBmpData = (BYTE**)new char[newDataSize]; // den Speicher allokieren
    memset(newBmpData, 0x00, newDataSize); // alles auf 0x00 setzen
    
    for(int curLine = 1; curLine <= height; curLine++) // jede Zeile..
            for(int curPix = 1; curPix <= width; curPix++) // ..und jeden Pixel einzeln kopieren, oder in diesem Fall auf 0xff setzen
            {
                    // SEGMENTATION FAULT schon beim 1. Schleifendurchlauf:
                    *((BYTE*)newBmpData + ((height-curLine) * (width *3 +newAdd) + (3* (curPix-1) +0))) = 0xff;  
            }
    
    [....]
    

    Hier die aufschl├╝sselung der Fehlerhaften Zeile (Wobei ich denke das das nicht von bedeutung ist da ja der gleiche Code unter windows funktioniert!):

    newBmpData + 
    (
         (height-curLine) // ein .bmp wird "auf dem Kopf" gespeichert -> wenn ich zB die 2. pixelreihe von oben anspringen will muss ich in wirklichkeit die 2. von unten anspringen
         * (width*3 + newAdd) // width * 3 weil jedes Pixel 3 Byte breit is, +newAdd weil die Pixelreihen auf ein vielfaches von 4 aufgerundet werden 
         + (3 * (curPix)) // curPix ist der pixel den ich gerade aus der oben referenzierten reihe haben will, 3* weil eben ein pixel 3 byte umfasst
    )
    

    Was ich schon rausgefunden hab bzw was es vll zu wissen gibt:

    • Die klasse wird jedesmal mit dem gleichen Input Bild und den gleichen Funktionsparametern gef├╝ttert!
    • height, curLine, width, newAdd und curPix haben unter Windows und Linux den selben wert
    • newDataSize ist bei beiden OSen gleich gro├č
    • newBmpData ist nicht NULL, egal ob es mit malloc() oder mit new[] allokiert wird
    • BYTE wird unter Linux so definiert: #define BYTE unsigned char*

    Ich hoffe ihr k├Ânnt mir sagen was ich hier ├╝berseh ­čśĽ

    Schonmal vielen vielen Dank f├╝r jede Hilfe!



  • PointerAreEvil schrieb:

    BYTE** newBmpData = (BYTE**)new char[newDataSize]; // den Speicher allokieren
    

    Das sieht verd├Ąchtig aus. Warum Doppelpointer? Offenbar willst du doch die Bilddaten ablegen. Sinnvoller scheint mir hier

    BYTE* newBmpData = new BYTE[newDataSize];
    
    • BYTE wird unter Linux so definiert: #define BYTE unsigned char*

    Was hei├čt "wird definiert"? Von dir oder von irgendeiner Library, die du benutzt? #define zum Typen definieren ist ziemlicher Murks, aber BYTE als Zeiger zu definieren ist schon halb kriminell.

    typedef unsigned char BYTE;
    


  • Vielen Dank f├╝r deinen Post!

    Also dass mit dem "#define BYTE unsigned char*" war ein Schreibfehler, ich hatte schon "unsigned char"!

    Hab jetzt mal dein typedef ├╝bernommen, danke!

    "BYTE** newBmpData" war weil ich in anderen Bereichen der Klasse, zumindest in fr├╝heren versionen mit einem char** gearbeitet hab.
    Hab das jetzt aber komplett auf BYTE* umgeschrieben, der Fehler bleibt aber ­čśĽ

    Wie gesagt, selber code l├Ąuft unter Windows..
    Gibts da irgend einen Unterschied den ich ├╝bersehe??

    Danke schonmal f├╝r eure Antworten!



  • Da Du nicht zu wissen scheinst, was Du tust, solltest Du folgende Dinge ganz besonders meiden:
    - C-style Casts
    - reinterpret_cast
    - #define

    Das, was Du machen willst, geht ganz sicher auch ohne solche Hacks.



  • sehe ich auch so kr├╝melkacker

    ausserdem ist nicht 100pro gesagt dass es unter windows klappt. linux k├Ânnte vielleicht einfach nur merken dass du auf speicher der dir nicht geh├Ârt zugreifst und schmeisst deswegen eine warnung. windows merkt das nicht oder hat dir ZUF├äLLIG diesen speicher auch zugewiesen.

    aber auf jeden fall:

    PointerAreEvil schrieb:

    for(int curLine = 1; curLine <= height; curLine++) {
        for(int curPix = 1; curPix <= width; curPix++)
    

    das sieht schonmal etwas komisch aus, denn arrays beginnen in C/C++ bei 0 und enden bei n-1. ok, so genau hab ich mich da nicht reingedacht, aber du subtrahierst ja die z├Ąhler von dem maximalwert, dann w├Ąrs wiederum richtig...

    was du machen k├Ânntest: du rechnest dir ja im prinzip eine zahl aus und addierst diese zu deinem speicher wert um darauf zu zugreifen
    speicher dir die zahl einfach mal in einer zus├Ątzlichen variable und pr├╝f jeden durchgang ob diese zahl zuf├Ąllig gr├Âsser bzw gleich deiner newDataSize ist
    wenn ja dann hast du deinen fehler inform von ausserhalb der array grenzen geschrieben. und dann musst du das ganze nochmal ├╝berdenken...

    EDIT: nicht richtig geguckt ­čśú
    ist ja schon im ersten durchlauf, wobei das mit der zus├Ątzlichen variable k├Ânnte doch klappen da du ja von hinten dran gehst

    EDIT2: ­čśâ ein schelm wer von hinten versaut interpretiert :DD



  • Ich hab keine Ahnung warum, aber nachdem ich einen BMP Header angepasst hab funktionierts oO
    Der hat aber mit dem Code eigentlich nichts zu tun, wtf? Naja egal ­čśâ

    Daf├╝r hab ich jetzt wo anders ne Segmentation Fault, aber die sollt ich alleine in den Griff bekommen ­čśâ

    @ Skym0sh0 : Das hat schon seine Richtigkeit das ich bei 1 anfange zu z├Ąhlen, wurde aus kompatibilit├Ątsgr├╝nden mit bereits vorhandenem Code gemacht, auf die Einhaltung der Buffergrenzen hab ich auch geachtet! (und auch wenn hier scheinbar einige meinen ich hab gar keine Ahnung von dem was ich tue, w├╝rd ich so nicht unterschreiben ­čśë )

    newBmpData ist 1056 Bytes gro├č und das h├Âchste an das geschrieben wird ist newBmpDAta + 1053 (der Unterschied kommt vom aufrunden auf ein vielfaches von 4!)

    Auch wenn ich irgendwie keine Ahnung hab warum das vorher nicht funktioniert hat (und schon an meinen geistigen F├Ąhigkeiten zweifle) bedanke ich mich recht herzlich bei den Leuten die mir hier geholfen haben, ist echt eins der besten Foren das ich kenne!

    Vielen Dank!



  • PointerAreEvil schrieb:

    Ich hab keine Ahnung warum, aber nachdem ich einen BMP Header angepasst hab funktionierts oO
    Der hat aber mit dem Code eigentlich nichts zu tun, wtf? Naja egal ­čśâ

    Typisches undefiniertes Verhalten. Das ist alles andere als egal. Wenn du die Fehler nun ignorierst, wirst du sp├Ąter geh├Ârig auf die Schnauze fallen.

    Und generell kann ich den anderen nur zustimmen. Verzichte auf Low-Level-Frickeleien und benutze die Abstraktionsmechanismen, die C++ bietet. Du brauchst weniger Zeit und Aufwand zur Entwicklung, zudem wird dein Code ├╝bersichtlicher, sicherer und nicht selten auch schneller.



  • Nach meiner Erfahrung ist Linux etwas pingeliger, bzw. der gcc/g++ unter linux. Was unter Windows l├Ąuft, muss daher nicht auch unter Linux sofort tun.
    Gerade wenn man so abenteuerliches Pointergefrickel macht wie du da...
    ... kannst ja mal den ddd anschmeissen...


Log in to reply