Frage

Meine Gedanken zum Thema Funktionszeiger heute wandern, und ich kam mit dem folgende Szenario in meinem Kopf:

__stdcall int function (int)
{
    return 0;
}

int main()
{
    (*(int(*)(char*,char*))function)("thought", "experiment");
    return 0;
}

AFAIK diesem Code verfälschen würde den Stapel, so welche Arten von Fragen könnte ich suchen, wenn ich diesen Code lief?

ich tun würde dies zu untersuchen, ich aber von meiner dev Maschine Ich bin weg eine Woche.

EDIT: Halten Sie auf einem zweiten, ich habe ein bisschen mehr nachgedacht. Wie in den Kommentaren beobachtet worden, hat die Absicht dieses Code einen Parameter auf dem Stapel gelassen wurde, wenn alles gesagt und getan ist (Anrufer legt zwei params auf dem Stapel, Aufgerufenen - nur einen param erwartet - erscheint nur ein off ). Da jedoch meine Besetzung nicht Erwähnung der Aufrufkonvention machen, bin ich weg Gießen stdcall, zumindest aus der Sicht des Anrufers? int function (int) wird immer noch eine param vom Stapel pop, aber nicht der Anrufer zurückkommen um die Funktion zu denken ist __cdecl (Standardeinstellung) wegen der Besetzung? (Das heißt insgesamt drei params geknallt?)

EDIT2: Die Antwort auf diese zweite Frage, wie Rob bestätigt, ja. Ich hätte neu zu formulieren __stdcall, wenn ich einen param auf dem Stapel verlassen wollte:

(*(__stdcall int(*)(char*,char*))function)("thought", "experiment");
War es hilfreich?

Lösung

Sie rufen die Funktion, als ob es _cdecl die den Anrufer bedeutet die Argumente schiebt und den Stapel bereinigt.

Die Empfangsfunktion ist _stdcall, die der Angerufene den Stapel bereinigt impliziert. Der Angerufene erwartet ein einziges Argument so 4 Bytes vom Stapel pop wird.

Wenn die Funktion der Anrufer gibt dann zwei Zeiger Pop-off (vorher auf zwei Zeigern gedrückt hat), so dass Ihr Stapel durch 4 Bytes beschädigt werden.

Beide Aufrufkonventionen verwenden die gleiche Rückholmechanik, und haben die gleichen Registerregeln (EAX, ECX und EDX sind nicht erhalten). Siehe wikipedia für weitere Details.

Je nach Stapelrahmen Layout und die Ausrichtung dieses Mismatch eine Reihe von Effekten führen könnte. Wenn Sie Glück haben, dann bekommen Sie mit ihm weg. Wenn nicht könnten Sie vermasseln die Absenderadresse Ihrer Hauptfunktion, wodurch das Programm zum Absturz bringen, wenn es Zweige zu wem-weiß-wo. Wenn der Compiler eine Art von Stack-Guard gespritzt hat Korruption zu fangen, dann wird es wahrscheinlich, dass diese erkennen und das Programm abbrechen.

Andere Tipps

Nein, wird es auf keinen Fall einen blauen Bildschirm verursachen. Kein Benutzermodus-Prozess ist in der Lage, das zu tun. Selbst wenn ein solcher Fehler im Kernel-Modus-Code, würde die BSOD nur auftreten, nachdem ungültigen Speicherzugriff oder Weitergabe falscher Argumente an eine Funktion.

Sie sind einfach verderbliche private Speicher des Prozesses, und die Korruption kann später in einem ungültigen Betrieb (oder auch nicht) führen (z. B. einen Zeiger auf ungültige Speicher dereferencing). Wenn dies geschieht, beendet das O Ihren Prozess, aber nicht früher.

Ich glaube, Sie würden in diesem Fall ‚undefiniert Verhalten‘ haben.

Von dem C Standard : (Ich würde annehmen, dass es das gleiche ist in C ++)

  

768 Wenn   ein umgebautes Zeiger wird verwendet, um anzurufen   Funktion, deren Typ nicht kompatibel   mit dem spitzen zu geben, das Verhalten   nicht definiert ist.

Edit: Auf den meist Betriebssystem, diese Art von Fehlern wäre Ihr gesamtes Betriebssystem nicht zu Problemen führen. Aber es wäre nicht definiert Probleme in Ihrem Programm führt. Es wäre sehr schwierig für ein Benutzermodus-Programm in der Lage sein, einen Blue-Screen zu führen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top