Seite 1 von 1

Absturz bei Aufruf der Funktion memset

Verfasst: 28.01.2011, 12:52
von HeReSY
Hallo,

in meinem Programm nutze ich memset um den Inhalt eines array's auf Null zu setzten

Code: Alles auswählen

unsinged char key[16];
...
memset(key, 0x00, sizeof(key));
So, jetzt bekomme ich irgendwann einmal in meinem Programm einen Segfault, der auf diese Stelle verweist.
Da stellt sich mir natürlich die Frage, was kann bei einem memset alles so falsch laufen?

Habe anschließend mal gegoogelt und eine ungereimtheit gefunden.
Einige rufen memset so auf, wie es bei mir der Fall ist, andere wiederum rufen es wie folgt auf.

Code: Alles auswählen

memset(&key, 0x00, sizeof(key));
Welches der beiden Fälle ist denn nun richtig? Bisher ist für mich immer der obige Fall richtig gewesen, da er ja ein painter auf das erste element des Array's ist.
Im zweiten Fall, erhalte ich meiner Meinung nach aber den Pointer des Pointers, oder etwa nicht?

HeReSY

Re: Absturz bei Aufruf der Funktion memset

Verfasst: 28.01.2011, 14:06
von Schrompf
Doch, da hast Du Recht. Manche Leute schreiben ein &(bla[0]), also die Adresse des ersten Elements. Das ist aber nur syntaktischer Bonus, der zumindest für schlichte C-Arrays weggelassen werden kann.

Der Absturz liegt dann wohl an was anderem. Setze mal einen Breakpoint drauf und schau, wie zu dem Zeitpunkt "key" aussieht. Evtl. hast Du lokal eine andere Variable mit Namen "key" definiert, weswegen das globalere Array dann ausgeblendet wird.

Re: Absturz bei Aufruf der Funktion memset

Verfasst: 28.01.2011, 14:40
von BeRsErKeR
HeReSY hat geschrieben:

Code: Alles auswählen

memset(&key, 0x00, sizeof(key));
Welches der beiden Fälle ist denn nun richtig? Bisher ist für mich immer der obige Fall richtig gewesen, da er ja ein painter auf das erste element des Array's ist.
Im zweiten Fall, erhalte ich meiner Meinung nach aber den Pointer des Pointers, oder etwa nicht?
Korrekt. Die zweite Variante ist nicht der richtige Weg. So einen memset Aufruf (mit dem &) nutzt man in der Regel für normale Instanzen:

Code: Alles auswählen

struct foo
{
int x;
float y;
};

...

foo f;
memset(&f, 0, sizeof(f));
Oder man nimmt die Variante von Schrompf, aber das macht in meinen Augen eher dann Sinn, wenn man nur einen bestimmten Teil setzen will.

Mit dem sizeof am Ende solltest du übrigens vorsichtig sein. Bei dynamischen Arrays kannst du das so nicht machen, das klappt nur bei statischen Arrays.

Re: Absturz bei Aufruf der Funktion memset

Verfasst: 28.01.2011, 14:48
von HeReSY
Danke für die Antworten,

da das Array eine feste Größe hat, kann ich das an der Stelle auch ruhigen Gewissens so machen.
Das was mich noch ein wenig verwirrt ist, dass beide memset aufrufe, so wie ich sie beschrieben habe auch funktionieren.
Eigentlich müsste doch beim zweiten memset(&key...) der Compiler ne Fehlermeldung oder mindestens eine Warnung ausgeben, das tut er allerdings nicht.

Habe mir dann dazu auch mal den Assembler-Code angeschaut, den der Compiler erzeugt. Es wird an diesen Stellen überhaupt kein memset aufgerufen, also kann der Fehler letztendlich nicht am memset liegen. Der Compiler beschreibt einfach nur jeweils 32bit pointer mit 0.
Habe das ganze dann auch mal mit einer for-Schleife getestet. Hierbei nutzt der Compiler dann auch memset. Allerdings funktioniert dann mein Programm nicht mehr richtig. wieseo weshalb auch immer.

Re: Absturz bei Aufruf der Funktion memset

Verfasst: 28.01.2011, 15:44
von Krishty
HeReSY hat geschrieben:Eigentlich müsste doch beim zweiten memset(&key...) der Compiler ne Fehlermeldung oder mindestens eine Warnung ausgeben, das tut er allerdings nicht.
U.a. deshalb ist memset() ja auch so gefährlich.
HeReSY hat geschrieben:Habe mir dann dazu auch mal den Assembler-Code angeschaut, den der Compiler erzeugt. Es wird an diesen Stellen überhaupt kein memset aufgerufen, also kann der Fehler letztendlich nicht am memset liegen. Der Compiler beschreibt einfach nur jeweils 32bit pointer mit 0.
memset() ist als Intrinsic Function bekannt, der Compiler kennt also ihr Verhalten und es steht ihm frei, gleichwertigen optimierten Text zu erzeugen statt die Funktion aufzurufen.
HeReSY hat geschrieben:Allerdings funktioniert dann mein Programm nicht mehr richtig. wieseo weshalb auch immer.
Wahrscheinlich aus dem selben Grund, aus dem auch der Segmentation Fault kommt: Irgendwo irgendwas kaputtgemacht. Falls du VCpp benutzt: /GS aktiviert, mal mit dem AppVerifier ausgeführt?

Die beste Methode, das Array zu Null zu intialisieren, ist übrigens immernoch unsinged char key[16] = { 0x00 }; ;)

Gruß, Ky

Re: Absturz bei Aufruf der Funktion memset

Verfasst: 28.01.2011, 18:32
von HeReSY
Benutze nur den Compiler von Microsift. Als IDE den Qt-Creator.

Ich würde mein key gerne so initialisieren, allerdings ist das ne member von meiner Klasse, und da geht das leider nicht so.

Re: Absturz bei Aufruf der Funktion memset

Verfasst: 28.01.2011, 18:40
von Krishty
Das geht in der Initialisierungsliste des K’tors, indem du key() schreibst (Default Initialization bedeutet bei POD Arrays immer Zero Initialization). VC schmeißt dann eine Warnung (weil das Verhalten erst vor einigen Jahren hinzugefügt wurde), aber die kannst du ignorieren / abschalten.

Re: Absturz bei Aufruf der Funktion memset

Verfasst: 28.01.2011, 21:54
von BeRsErKeR
HeReSY hat geschrieben:Eigentlich müsste doch beim zweiten memset(&key...) der Compiler ne Fehlermeldung oder mindestens eine Warnung ausgeben, das tut er allerdings nicht.
Der Compiler meckert nicht, weil der erste Parameter ein void-Pointer ist. Und ein Pointer auf einen Pointer ist immer noch ein Pointer.