Coroutinen - Status speichern

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Virus
Beiträge: 38
Registriert: 20.09.2002, 17:28
Kontaktdaten:

Coroutinen - Status speichern

Beitrag von Virus »

Hallo,

ich beschäftige mich gerade ein wenig mit Coroutinen (via setjmp(), longjmp() und manueller Stack-Speicherung). Das funktioniert auch alles ganz gut, jetzt möchte ich jedoch gerne dei Ausführung des Programms unterbrechen (irgendwann bei einem Kontextwechsel) und den Status speichern (Stack, Registerinhalte). Das ganze soll später wieder geladen werden können und die Coroutinen sollen an der Stelle fortgesetzt werden, an denen die Unterbrechnung stattgefunden hat.

Leider funktioniert das nicht so ganz, bzw. bin ich mir nicht sicher, was alles gemacht werden muss, damit das klappt. Ich benutze (als Beispiel) folgenden Code. Wenn das Argument "write" übergeben wird, werden zwei Coroutinen (ind & fib) ausgeführt (eine Weile lang) und schließlich deren Attribute in eine Datei geschrieben. Beim Laden werden diese Datein gelesen - jedoch knallts beim ersten Aufruf von longjmp().

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

typedef unsigned int uint;
typedef unsigned short word;
typedef unsigned char byte;

#ifdef __GNUC__
#define NOINLINE __attribute__((noinline))
#else
#define NOINLINE __declspec(noinline)
#endif

#include <setjmp.h>
#include <fstream>
#include <string>

using namespace std;

enum {
	STKPAD = 1 << 16, STKSAV = 1 << 10
};

template<typename T>
struct coroutine {

	volatile uint state;
	volatile char* stkptrH;
	volatile char* stkptrL;
	jmp_buf PointA, PointB;
	char stack[STKSAV];

	coroutine() {
		state = 0;
	}

	NOINLINE // necessary for IntelC + my_setjmp.h
	void yield(int value) {
		char curtmp;
		stkptrL = (&curtmp) - 16; // -16 is necessary for MSC
		if (setjmp(PointB) == 0) {
			state = value;
			memcpy(stack, (char*) stkptrL, stkptrH - stkptrL);
			longjmp(PointA, 1);
		}
	}

	NOINLINE // necessary for MSC, to avoid allocation of stktmp before setjmp()
	void call_do_process() {
		char stktmp[STKPAD];
		stkptrH = stktmp;
		((T*) this)->do_process();
	}

	uint call(void) {
		if (setjmp(PointA) == 0) {
			if (state) {
				memcpy((char*) stkptrL, stack, stkptrH - stkptrL);
				longjmp(PointB, 1);
			}
			call_do_process();
		}
		return state;
	}

	void save(string pFileName) {
		ofstream f;
		f.open(pFileName.c_str(), ios::out | ios::binary | ios::trunc);
		f.write((char*) &state, sizeof(state));
		f.write((char*) &stkptrH, sizeof(stkptrH));
		f.write((char*) &stkptrL, sizeof(stkptrH));
		f.write((char*) &PointA[0], sizeof(__jmp_buf_tag ));
		f.write((char*) &PointB[0], sizeof(__jmp_buf_tag ));
		f.write(stack, STKSAV);
		f.close();
	}

	void read(string pFileName) {
		ifstream f;
		f.open(pFileName.c_str(), ios::in | ios::binary);
		f.read((char*) &state, sizeof(state));
		f.read((char*) &stkptrH, sizeof(stkptrH));
		f.read((char*) &stkptrL, sizeof(stkptrH));
		f.read((char*) &PointA[0], sizeof(__jmp_buf_tag ));
		f.read((char*) &PointB[0], sizeof(__jmp_buf_tag ));
		f.read(stack, STKSAV);
		f.close();
		memcpy((char*) stkptrL, stack, stkptrH - stkptrL);
	}
};

struct indexX: coroutine<indexX> {

	void do_process(void) {
		uint a = 1;
		while (1) {
			yield(a);
			a++;
		}
	}

};

struct fibonacci: coroutine<fibonacci> {

	void do_process(void) {
		uint a = 0, b = 1;
		while (1) {
			yield(b);
			b = b + a;
			a = b - a;
		}
	}

};

int main(int argc, char** argv) {

	indexX ind;
	fibonacci fib;
	printf("%p\n", &ind);

	char indFn[] = "ind";
	char fibFn[] = "fib";

	if (argc < 2) {
		printf("too few args.\n");
		return 0;
	}

	if (strcmp("write", argv[1]) == 0) {
		printf("write.\n");
		for (int i = 0; i < 20; i++) {
			printf("%i:%i ", ind.call(), fib.call());
			ind.call();
			fib.call();
		}

		ind.save(indFn);
		fib.save(fibFn);

		printf("\n");
	} else {
		printf("read.\n");

		ind.read(indFn);
		fib.read(fibFn);

		for (int i = 0; i < 20; i++) {
			printf("%i:%i ", ind.call(), fib.call());
			printf("\n");
		}
	}

	printf("done.\n");
	return 0;
}
Ich führe das ganze mit dem gdb aus, d.h. die Position des Stack im Speicher ist in beiden Fällen die gleiche (im write und anschließenden read fall), d.h. ich kann die Stackpointer (low und high) weiterhin benutzen (denke ich mir so zumindest). Ich bekomme dennoch folgende Ausgabe:

Code: Alles auswählen

(gdb) run write
Starting program: /home/thomas/workspaces/Studienarbeit/SetJump/Debug/SetJump write
0x7fffffffdc40
write.
1:1 3:2 5:5 7:13 9:34 11:89 13:233 15:610 17:1597 19:4181 21:10946 23:28657 25:75025 27:196418 29:514229 31:1346269 33:3524578 35:9227465 37:24157817 39:63245986 
done.

Program exited normally.
(gdb) run read
Starting program: /home/thomas/workspaces/Studienarbeit/SetJump/Debug/SetJump read
0x7fffffffdc40
read.

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff72eda7e in ?? () from /lib/libc.so.6
(gdb) 
Klappt also nicht. Warum nicht?

Wäre super wenn mir jemand weiterhelfen könnte. Es ist für mich (zumindest erstmal) vollkommen in Ordnung, irgendwelche platformspezifischen Dinge zu machen oder sonstige Einschränkungen vorzunehmen. Wäre halt toll, wenns erstmal prinzipiell halbwegs funktioniert.

Ich hoffe mal ihr könnt mir weiterhelfen. Schönes Wochenende euch allen,

Thomas
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Coroutinen - Status speichern

Beitrag von eXile »

Ich nehme einfach mal ins Blaue hinein an, dass es im memcpy von read kracht. Kann man einfach so auf dem Stack memcpy'ien, wie man lustig ist (denn das legt ja auch Variablen auf den Stack ab)? Als ich selber mal etwas in die Richtung SSDT-Hooking gemacht habe, musste ich mir meinen Stack mit Assembler wieder zusammelbasteln (und alle Funktionen waren so wie so in Assembler, weil ich mich nicht auf die Registerzuweisungen von Variablen durch Visual Studio verlassen konnte).
Virus
Beiträge: 38
Registriert: 20.09.2002, 17:28
Kontaktdaten:

Re: Coroutinen - Status speichern

Beitrag von Virus »

Nein, krachen tut es bei dem Aufruf von longjmp() in der methode coroutine::call() (im laden fall).

Der Sinn vom memcpy des Stacks ist es ja eben, die lokalen variablen etc. zu speichern. Problematisch ist jedoch, dass (beim Neuladen aus der Datei) der stackpointer und framepointer auch richtig wieder gesetzt werden muss (auch von tiefer gelegenen Frames). Aber eigentlich sollte das hier ja nicht das Problem sein, da der Stack ja offensichtlich bei beiden Programmläufen an der gleichen Stelle liegt? Oder sehe ich da was falsch?
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Coroutinen - Status speichern

Beitrag von eXile »

Ich hab mir nun sogar einmal die Mühe gemacht, das unter VS zum Laufen zu kriegen. Einzige Änderung war, alle Zeilen mit sizeof(__jmp_buf_tag)) durch sizeof(jmp_buf) zu ersetzen. Auch hier kriege ich bei mehreren Durchläufen dieselbe (virtuelle) Speicheradresse ausgegeben. Trotzdem schmiert er beim memcpy'ien ab.

Nachtrag: Du hast da außerdem auch noch zwei Copy-n-Paste-Fehler drin bei den sizeofs.

Noch ein Nachtrag: Mir ist vollkommen unklar, warum du überhaupt nach stkptrL schreiben darfst. Wenn der Stack dort nicht vom Programm reingewachsen ist, darf das Programm auch nicht einfach auf diese Speicherseiten zugreifen, und wird vom Betriebssystem platt gemacht.

Noch ein Nachtrag: Verdacht bestätigt, wenn du einfach vor ind.read ein char stktmp[STKPAD*2]; (im Debug-Build, da unreferenziert) reinhaust, ist das gültig. Kein Wunder: Die Page-Größe bei mir ist 4096 Bytes, dein stktmp, was ja bei einem write-Aufruf vorher auf dem Stack liegt, ist 65536 Bytes groß, also 16 Pages, die nicht vom Betriebsystem mit irgendeiner Schreibberechtigung für dich vorliegen. Du kannst nicht einfach im Speicher rumschreiben, wie du willst.
Virus
Beiträge: 38
Registriert: 20.09.2002, 17:28
Kontaktdaten:

Re: Coroutinen - Status speichern

Beitrag von Virus »

Hi,

danke erstmal für deine Hilfe. Das memcpy()in der read-methode hat da überrings nichts zu suchen (der stack wird ja später in der call() methode kopiert), dass ist nur ein Überbleibsel von einigen Experimenten. Der gesamte Code sieht bei mir jetzt wie folgt aus:

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

typedef unsigned int uint;
typedef unsigned short word;
typedef unsigned char byte;

#ifdef __GNUC__
#define NOINLINE __attribute__((noinline))
#else
#define NOINLINE __declspec(noinline)
#endif

#include <setjmp.h>
#include <fstream>
#include <string>

using namespace std;

enum {
	STKPAD = 1 << 16, STKSAV = 1 << 10
};

template<typename T>
struct coroutine {

	volatile uint state;
	volatile char* stkptrH;
	volatile char* stkptrL;
	jmp_buf PointA, PointB;
	char stack[STKSAV];

	coroutine() {
		state = 0;
	}

	NOINLINE // necessary for IntelC + my_setjmp.h
	void yield(int value) {
		char curtmp;
		stkptrL = (&curtmp) - 16; // -16 is necessary for MSC
		if (setjmp(PointB) == 0) {
			state = value;
			memcpy(stack, (char*) stkptrL, stkptrH - stkptrL);
			longjmp(PointA, 1);
		}
	}

	NOINLINE // necessary for MSC, to avoid allocation of stktmp before setjmp()
	void call_do_process() {
		char stktmp[STKPAD];
		stkptrH = stktmp;
		((T*) this)->do_process();
	}

	uint call(void) {
		if (setjmp(PointA) == 0) {
			if (state) {
				memcpy((char*) stkptrL, stack, stkptrH - stkptrL);
				longjmp(PointB, 1);
			}
			call_do_process();
		}
		return state;
	}

	void save(string pFileName) {
		ofstream f;
		f.open(pFileName.c_str(), ios::out | ios::binary | ios::trunc);
		f.write((char*) &state, sizeof(state));
		f.write((char*) &stkptrH, sizeof(stkptrH));
		f.write((char*) &stkptrL, sizeof(stkptrL));
		f.write((char*) &PointA[0], sizeof(__jmp_buf_tag ));
		f.write((char*) &PointB[0], sizeof(__jmp_buf_tag ));
		f.write(stack, STKSAV);
		f.close();
	}

	void read(string pFileName) {
		ifstream f;
		f.open(pFileName.c_str(), ios::in | ios::binary);
		f.read((char*) &state, sizeof(state));
		f.read((char*) &stkptrH, sizeof(stkptrH));
		f.read((char*) &stkptrL, sizeof(stkptrL));
		f.read((char*) &PointA[0], sizeof(__jmp_buf_tag ));
		f.read((char*) &PointB[0], sizeof(__jmp_buf_tag ));
		f.read(stack, STKSAV);
		f.close();
	}
};

struct indexX: coroutine<indexX> {

	void do_process(void) {
		uint a = 1;
		while (1) {
			yield(a);
			a++;
		}
	}

};

struct fibonacci: coroutine<fibonacci> {

	void do_process(void) {
		uint a = 0, b = 1;
		while (1) {
			yield(b);
			b = b + a;
			a = b - a;
		}
	}

};

int main(int argc, char** argv) {

	indexX ind;
	fibonacci fib;
	printf("%p\n", &ind);

	char indFn[] = "ind";
	char fibFn[] = "fib";

	if (argc < 2) {
		printf("too few args.\n");
		return 0;
	}

	if (strcmp("write", argv[1]) == 0) {
		printf("write.\n");
		for (int i = 0; i < 20; i++) {
			printf("%i:%i ", ind.call(), fib.call());
		}

		ind.save(indFn);
		fib.save(fibFn);

		printf("\n");
	} else {
		char stktmp[STKPAD*2];

		printf("read.\n");

		ind.read(indFn);
		fib.read(fibFn);

		for (int i = 0; i < 20; i++) {
			printf("%i:%i ", ind.call(), fib.call());
			printf("\n");
		}
	}

	printf("done.\n");
	return 0;
}
Wie gesagt, bei mir tritt der Fehler erst bei den longjmp()-Aufruf auf, memcpy macht keine Probleme (auch wenn es durchaus verständlich ist, dass es probematisch ist), aber die von dir vorgehnommene zusätzliche Stackvergrößerung sollte zumindest das Problem ja beheben. Dennoch kracht es eben bei dem longjmp()-Aufruf in der call() methode.

Was passiert bei dir? Oder läuft etwa alles, wie es soll?
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Coroutinen - Status speichern

Beitrag von eXile »

OK, im Release-Build habe ich den Fehler nun reproduzieren können:

Code: Alles auswählen

  <?xml version="1.0" encoding="UTF-8" standalone="no" ?> 
- <avrf:logfile xmlns:avrf="Application Verifier">
- <avrf:logSession TimeStarted="2011-03-27 : 14:35:33" PID="2932" Version="2">
- <avrf:logEntry Time="2011-03-27 : 14:35:54" LayerName="Heaps" StopCode="0x13" Severity="Error">
  <avrf:message>First chance access violation for current stack trace.</avrf:message> 
  <avrf:parameter1>11f60f - Invalid address causing the exception.</avrf:parameter1> 
  <avrf:parameter2>7855af0c - Code address executing the invalid access.</avrf:parameter2> 
  <avrf:parameter3>12f33c - Exception record.</avrf:parameter3> 
  <avrf:parameter4>12f358 - Context record.</avrf:parameter4> 
- <avrf:stackTrace>
  <avrf:trace>vrfcore!VfCoreRedirectedStopMessage+81 (d:\avrf\source\base\avrf\avrf30\vrfcore\stopredirect.cpp @ 103)</avrf:trace> 
  <avrf:trace>vfbasics!VerifierStopMessage+292 (d:\avrf\source\base\avrf\avrf30\providers\basics\basics.c @ 1214)</avrf:trace> 
  <avrf:trace>vfbasics!AVrfpCheckFirstChanceException+c8 (d:\avrf\source\base\avrf\vrfcommon\support.c @ 1106)</avrf:trace> 
  <avrf:trace>vfbasics!AVrfpVectoredExceptionHandler+16 (d:\avrf\source\base\avrf\vrfcommon\support.c @ 321)</avrf:trace> 
  <avrf:trace>ntdll!RtlDeleteAce+c36f ( @ 0)</avrf:trace> 
  <avrf:trace>ntdll!wcstol+b6 ( @ 0)</avrf:trace> 
  <avrf:trace>ntdll!KiUserExceptionDispatcher+e ( @ 0)</avrf:trace> 
  <avrf:trace>fibers!coroutine<fibonacci>::call+38 (c:\dokumente und einstellungen\<user>\desktop\fibers\fibers\main.cpp @ 60)</avrf:trace> 
  <avrf:trace>fibers!main+9d (c:\dokumente und einstellungen\<user>\desktop\fibers\fibers\main.cpp @ 147)</avrf:trace> 
  <avrf:trace>KERNEL32!RegisterWaitForInputIdle+49 ( @ 0)</avrf:trace> 
  </avrf:stackTrace>
  </avrf:logEntry>
  </avrf:logSession>
  </avrf:logfile>

Nachtrag: Grummel, nun gehts tatsächlich bis zum longjmp. Der Optimierer war mal wieder zu schlau, also einfach

Code: Alles auswählen

volatile char stktmp[STKPAD*2];
stktmp[STKPAD*2-1] = 42;

printf("read. %d\n", stktmp[STKPAD*2-1]);
reinhauen.
Und es muss mir keiner hier erklären, dass das grottig ist; das hier ist wohl alles eher unter akademischen Gesichtspunkten zu verstehen, und nicht als Produktivcode.

Nachtrag: Meine aktuelle Vermutung ist, dass der EIP ins Nirvana zeigt.

Nachtrag: Sehr gut, ich Depp habe natürlich direkt deinen Code so modifziert, dass die ifs ausdefined werden - was man aber überhaupt nicht machen darf! Damit erst einmal alles wieder auf Anfang.

Nachtrag: Ich paste erst einmal den Code so weit hier rein:

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

typedef unsigned int uint;
typedef unsigned short word;
typedef unsigned char byte;

#ifdef __GNUC__
#define NOINLINE __attribute__((noinline))
#else
#define NOINLINE __declspec(noinline)
#endif

#include <setjmp.h>
#include <fstream>
#include <string>

using namespace std;

enum {
    STKPAD = 1 << 16, STKSAV = 1 << 10
};

template<typename T>
struct coroutine {

    volatile uint state;
    volatile char* stkptrH;
    volatile char* stkptrL;
    jmp_buf PointA, PointB;
    char stack[STKSAV];

    coroutine() {
        state = 0;
    }

    NOINLINE // necessary for IntelC + my_setjmp.h
        void yield(int value) {
            char curtmp;
            stkptrL = (&curtmp) - 16; // -16 is necessary for MSC
            if (setjmp(PointB) == 0) {
                state = value;
                memcpy(stack, (char*) stkptrL, stkptrH - stkptrL);
                longjmp(PointA, 1);
            }
    }

    NOINLINE // necessary for MSC, to avoid allocation of stktmp before setjmp()
        void call_do_process() {
            char stktmp[STKPAD];
            stkptrH = stktmp;
            ((T*) this)->do_process();
    }

    uint call(void) {
        if (setjmp(PointA) == 0) {
            if (state) {
                memcpy((char*) stkptrL, stack, stkptrH - stkptrL);
                longjmp(PointB, 1);
            }
            call_do_process();
        }
        return state;
    }

    void save(string pFileName) {
        ofstream f;
        f.open(pFileName.c_str(), ios::out | ios::binary | ios::trunc);
        f.write((char*) &state, sizeof(state));
        f.write((char*) &stkptrH, sizeof(stkptrH));
        f.write((char*) &stkptrL, sizeof(stkptrL));
        f.write((char*) &PointA[0], sizeof(jmp_buf ));
        f.write((char*) &PointB[0], sizeof(jmp_buf ));
        f.write(stack, STKSAV);
        f.close();
    }

    void read(string pFileName) {
        ifstream f;
        f.open(pFileName.c_str(), ios::in | ios::binary);
        f.read((char*) &state, sizeof(state));
        f.read((char*) &stkptrH, sizeof(stkptrH));
        f.read((char*) &stkptrL, sizeof(stkptrL));
        f.read((char*) &PointA[0], sizeof(jmp_buf ));
        f.read((char*) &PointB[0], sizeof(jmp_buf ));
        f.read(stack, STKSAV);
        f.close();
    }
};

struct indexX: coroutine<indexX> {

    void do_process(void) {
        uint a = 1;
        while (1) {
            yield(a);
            a++;
        }
    }

};

struct fibonacci: coroutine<fibonacci> {

    void do_process(void) {
        uint a = 0, b = 1;
        while (1) {
            yield(b);
            b = b + a;
            a = b - a;
        }
    }

};

int main(int argc, char** argv) {

    indexX ind;
    fibonacci fib;
    printf("%p\n", &ind);

    char indFn[] = "ind";
    char fibFn[] = "fib";

    if (argc < 2) {
        printf("too few args.\n");
        return 0;
    }

    if (strcmp("write", argv[1]) == 0) {
        printf("write.\n");

        for (int i = 0; i < 20; i++) {
            printf("%i:%i ", ind.call(), fib.call());
        }

        ind.save(indFn);
        fib.save(fibFn);

        printf("\n");
    } else {
        alloca(STKPAD * 2);

        printf("read.\n");

        ind.read(indFn);
        fib.read(fibFn);

        for (int i = 0; i < 20; i++) {
            printf("%i:%i ", ind.call(), fib.call());
        }
    }

    printf("done.\n");
    return 0;
}
Ich habe es aufgegeben, das im Release-Build zum Laufen zu kriegen. Der lässt dann einige Stackframes weg, und so wie ich das sehe brauchst du die an einigen Stellen. Ich habe die Stackallocation via alloca lösen müssen, weil dann der Compiler keine Chance hat, das aus dem zweiten if-Zweig rauszunehmen und direkt dem Stackframe von main hinzuzufügen. Aktuelle Ausgabe im Debug-Build:
0012FAD4
read.
21:10946 22:17711 23:28657 24:46368 25:75025 26:121393 27:196418 28:317811 29:51
4229 30:832040 31:1346269 32:2178309 33:3524578 34:5702887 35:9227465 36:1493035
2 37:24157817 38:39088169 39:63245986 40:102334155 done.
Das sieht doch gut aus :) (Selbstredend 0 errors, 0 warnings im Application Verifier, auch wenn das nicht unbedingt etwas sagen muss - schließlich hat der einen Debug-Heap und keinen Debug-Stack.)

Nachtrag: Der Code funktioniert nun auch im Release-Build. ಠ_ಠ.

Letzter Nachtrag: Dieser Post ist hiermit final, keine weiteren Edits mehr.
Virus
Beiträge: 38
Registriert: 20.09.2002, 17:28
Kontaktdaten:

Re: Coroutinen - Status speichern

Beitrag von Virus »

Hi,

vielen Dank erstmal für deine Zeit. Wenn ich das richtig sehe, hast du im Code also nur noch alloca(STKPAD * 2); hinzugefügt? Wenn es so bei dir klappt, zeigt es zumindest, das es prinzipell auf diese Art und Weise funktionieren sollte. Nur tut es das bei mir nicht :-( . Wie hast du das ganze genau ausgeführt? Komme ja dank MSDNAA auch an VS ran (kenne mich damit nur nicht aus ^^).

Danke für deine Hilfe,

Thomas
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Coroutinen - Status speichern

Beitrag von eXile »

Korrekt, ich habe nur das alloca hinzugefügt und die statische char-Array-Allokation entfernt. Wie ich schon sagte, ist dass einfach notwendig, weil im write-Teil ja bis zum Speichern des Stacks bereits zwei STKPAD-große Allokationen auf dem Stack durchgeführt wurden, d.h. der Stack so weit verschoben ist. Das alloca im read-Teil hat einfach hier nur die (unsaubere) Aufgabe, den Stackpointer entsprechend um STKPAD*2 zu verschieben, damit die gleichen Stackadressen wie im write-Teil gültig sind.

Um das auszuführen habe ich einfach eine leere Win32-Konsolenanwendung erstellt, mit der zusätzlichen Einstellung „leeres Projekt“. Dann habe ich eine neue .cpp-Datei erstellt, dort deinen / meinen veränderten Code reingepastet, und kompiliert (F7) und ohne Debugging gestartet (Strg+F5). Das ist standardmäßig der Debug-Build, um den Release-Build einzustellen muss man einfach das entsprechende Drop-Down-Feld auf Release stellen, und auf die gleiche Art und Weise das kompilieren und starten.

Nachtrag: Oder schau dir einfach das Video an.
Virus
Beiträge: 38
Registriert: 20.09.2002, 17:28
Kontaktdaten:

Re: Coroutinen - Status speichern

Beitrag von Virus »

Klappt nicht, TT

Kann aber auch nicht, da die Stackadresse beim Neustart jedes mal eine andere ist bei mir - was ja auch eigentlich zu erwarten ist. Kann man zaubern, dass das nicht mehr so ist?
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Coroutinen - Status speichern

Beitrag von Krishty »

seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Coroutinen - Status speichern

Beitrag von eXile »

Mit Address Space Layout Randomization kann man das in der Form sowieso vergessen: Da muss man schon in den jmp_buf Datenstrukturen den EIP und ESP (wahrscheinlich noch mehr) umbiegen.
Virus
Beiträge: 38
Registriert: 20.09.2002, 17:28
Kontaktdaten:

Re: Coroutinen - Status speichern

Beitrag von Virus »

Krishty hat geschrieben:/DYNAMICBASE:NO? ;)
Danke, dass isses und so funktionierts auch.
Antworten