Zugriffsverletzung in Visual Studio 2010



  • Hallo Gemeinde,

    in Visual Studio 2010 stürzt bei mir folgendes Programm in der return-Zeile der getFirstElement-Funktion ab:

    #include <stdio.h>
    
    int getFirstElement(int **arr)
    {
    	return arr[0][0];
    }
    
    int main()
    {
    	int arr[2][2] = {{1, 2},{1, 2}};
    	int i = getFirstElement(arr);
    	return 0;
    }
    

    Unbehandelte Ausnahme bei 0x[..]:
    Zugriffsverletzung beim Schreiben an Position 0x00000001.

    Wenn ich die Situation richtig einschätze, liegt das Problem bei Visual Studio. Hab jetzt schon in den Projekteinstellungen geguckt, ob man das Problem da beheben kann leider ohne Erfolg. Bei google bin ich auch nicht fündig geworden.

    Das Problem existiert übrigens nicht, wenn ich das ganze mit einem eindimensionalen Array mache.

    Hat jemand vielleicht einen Tipp?

    Vielen Dank im Voraus!



  • Oh, die Fehlermeldung ist von einem anderen Test.

    In diesem Fall lautet die Fehlermeldung entsprechend:

    Unbehandelte Ausnahme bei 0x[..]:
    Zugriffsverletzung beim Lesen an Position 0x00000001.



  • Nein, das Problem liegt nicht bei Visual Studio (außer daß der Compiler versäumt hat, dich vor der fehlerhaften Parameter-Übergabe zu warnen). Die Array-zu-Zeiger-Umwandlung funktioniert nur für eindimesionale Array, nicht für mehrdimensionale - dadurch geht dein Array-Zugriff in die Hosen.



  • Mich warnt cl.exe beim Kompilieren (cl test.c). Visual Studio 2010 macht das sicherlich auch.



  • Danke an Euch!

    Ihr habt Recht, hier gibt es auch eine Warnung. Trotzdem verwundert mich das. Zwischen einem 2-dim. Array und einem Pointer auf Pointer besteht doch eigentlich kein Unterschied, außer, dass dem Array bereits Speicher reserviert wurde, und die Zeiger (also arr[0], arr[1], ...) entsprechend initialisiert wurden.

    Ich möchte eine Funktion schreiben, bei der nich bekannt ist, ob der übergebene Wert ein statisch oder dynamisch erzeugtes Array ist. Wie würdet ihr das machen?

    Danke nochmal.



  • Jack985 schrieb:

    Ihr habt Recht, hier gibt es auch eine Warnung. Trotzdem verwundert mich das. Zwischen einem 2-dim. Array und einem Pointer auf Pointer besteht doch eigentlich kein Unterschied, außer, dass dem Array bereits Speicher reserviert wurde, und die Zeiger (also arr[0], arr[1], ...) entsprechend initialisiert wurden.

    Du bist anscheinend auch auf den Mythos reingefallen, daß Arrays und Zeiger identisch sind 😃

    Fakt ist, daß es einen großen Unterschied gibt zwischen einem Array (eine Sammlung von gleichartigen Objekten, die hintereinander im Speicher untergebracht sind) und einem Zeiger (eine einzelne Variable, die eine Adresse enthält). Allerdings kannst du mit einem Zeiger auf den Anfang eines Arrays deuten und per Index-Zugriff wie ein Array genutzt werden - dafür muß der Compiler nicht unbedingt wissen, wie groß das Array ist (nur wie groß die einzelnen Array-Elemente sind) - das passiert auch implizit, wenn du ein Array als Parameter übergibst.
    Zweidimensionale Arrays sind auch normale Arrays, nur mit dem Unterschied, daß ihre Elemente ebenfalls Arrays sind - die kannst du auch in einen Zeiger umwandeln (der dann auf Arrays vorgegebener Größe verweist - die Größe kennt der Compiler und kann sie für Zeiger-Arithmetik verwenden).



  • Jack985 schrieb:

    Trotzdem verwundert mich das. Zwischen einem 2-dim. Array und einem Pointer auf Pointer besteht doch eigentlich kein Unterschied, außer, dass dem Array bereits Speicher reserviert wurde, und die Zeiger (also arr[0], arr[1], ...) entsprechend initialisiert wurden.

    Das ist ein großer Unterschied
    Ein 2-dim Array ist auch nur ein normaler Zeiger, da er auf ein Speicherbereich zeigt. Wenn du weißt wie der Bereich aufgebaut ist, kannst du auch darauf zugreifen.

    int a[2][3]
    int i,j;
    ...
    a[i][j]==a+i*3+j //immer wahr, da es das selbe Element ist (für 0<=i<2, 0<=j<3).
    

    Ein Beispiel für ein Doppelzeiger ist z.B. argv mit argv[1][0] bekommst du das erste Zeichen vom zweiten Argument.
    Das ist im Speicher aber ganz anders aufgebaut.
    Das ist ein Array mit Zeigern. Die Zeiger zeigen auf Bereiche die auch ganz woanders liegen können.



  • Hallo,

    danke an alle, habs verstanden.

    So funktionierts:

    #include <stdio.h>
    
    int getFirstElement(int **arr)
    {
    	return arr[0][0];
    }
    
    int main()
    {
    	int i;
    	int arr[2][2] = {{1, 2},{3, 4}};
    	int *ptArr[2];
    	ptArr[0] = &arr[0];
    	ptArr[1] = &arr[1];
    
    	i = getFirstElement(ptArr);
    
    	return 0;
    }
    

Log in to reply