Unexpected error bei DLL

  • C/C++

    Unexpected error bei DLL

    Hallo Leute,

    ich hab folgendes Problem:
    Wenn ich meine DLL in ein Game Maker Projekt einbinden will, dann bleibt der GM entweder hängen oder es gibt einen "unexpected error".
    Ich hab erst letztens angefangen C++ zu lernen, deswegen kann ich mir nicht weiterhelfen. Wisst ihr woran es liegen kann?
    Ich arbeite mit Netbeans.

    Hier ist die DLL + Quell-Code. Ich hab einfach zum Testen eine Funktion erstellt, die eine Animation in einem vector abspeichert und den Index zurückgibt.
    Wenn ich vector weg lasse, also nicht auf meine Klassen zugreife, dann gibt es auch keinen Fehler. Ich weiß echt nicht weiter.

    Danke schon mal im Voraus.

    MfG

    Albert Einstein schrieb:

    Probleme kann man niemals mit derselben Denkweise lösen, durch die sie entstanden sind.
    Soweit ich weiß, ist das ganz normales C++, ohne irgendwelche Frameworks oder Libraries, was ich da benutze. Das einzige was ich benutze ist math.h, vector und map.
    Weiß keiner woran das liegen kann?

    Albert Einstein schrieb:

    Probleme kann man niemals mit derselben Denkweise lösen, durch die sie entstanden sind.

    Quellcode

    1. vector<Animation*> *animations;

    ist sicher nicht was du haben willst. Das wäre nämlich ein pointer auf einen vector, der aber erstmal noch auf nichts zeigt. D.h. es existiert auch erstmal kein vector, in dem man etwas speichern könnte. Wenn du dann also schreibst

    Quellcode

    1. animations->push_back(new Animation(bones,frames));

    dann dereferenzierst du einen pointer, der noch nicht initialisiert wurde.

    Schreibe stattdessen

    Quellcode

    1. vector<Animation*> animations;

    und

    Quellcode

    1. animations.push_back(new Animation(bones,frames));
    Oh man, wie konnte ich ich das übersehen ^^. Danke Bl@ckSp@rk!

    Aber:
    Ich bekomme immer noch einen "unexpected error". Ich weiß, dass der Fehler im Konstruktor von Animation geschieht, wenn ich in die maps ein Paar einfüge:
    Spoiler anzeigen

    Quellcode

    1. x->insert(pair* >(i,new vector()));
    2. y->insert(pair* >(i,new vector()));
    3. angle->insert(pair* >(i,new vector()));
    4. scale->insert(pair* >(i,new vector()));
    5. parent_angle->insert(pair* >(i,new vector()));
    6. parent_length->insert(pair* >(i,new vector()));
    7. sprite_xscale->insert(pair* >(i,new vector()));
    8. sprite_yscale->insert(pair* >(i,new vector()));
    9. sprite_index->insert(pair* >(i,new vector()));
    10. joint_xscale->insert(pair* >(i,new vector()));
    11. joint_yscale->insert(pair* >(i,new vector()));
    12. joint_index->insert(pair* >(i,new vector()));


    Jedenfalls, wenn ich es in Netbeans teste, sagt es mir, dass der RUN fehlschlägt, aber auch genau, dann wenn ich in der for-Schleife mehr in jede map einfüge. Wenn ich nur in bspw. x einfüge, dann ist der RUN erfolgreich.

    Was ist denn da falsch?

    Edit: Problem gelöst!
    Er lag in dieser Zeile:

    Quellcode

    1. this->x,y,angle,scale,parent_angle,parent_length,
    2. sprite_xscale,sprite_yscale,sprite_index,
    3. joint_xscale,joint_yscale,joint_index
    4. = new map* >();


    Es wurde anscheinend nur dem x ein neues Objekt zugewiesen und nicht den anderen nach dem Komma.
    Naja, Problem gelöst. Jetzt kann ich beruhigt schlafen. :)
    Danke nochmal, Bl@ackSp@rk!
    Nacht!

    MfG Trixt0r

    Albert Einstein schrieb:

    Probleme kann man niemals mit derselben Denkweise lösen, durch die sie entstanden sind.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Trixt0r“ ()

    Noch ein Hinweis warum

    Quellcode

    1. this->x,y,angle,scale,parent_angle,parent_length,
    2. sprite_xscale,sprite_yscale,sprite_index,
    3. joint_xscale,joint_yscale,joint_index = new map<unsigned int,vector<double>* >();

    nicht auf diese Weise funktioniert. Dazu muss man wissen was das Komma bedeutet. Dieses ist einfach ein binärer Operator, der erst den linken Ausdruck auswertet, dessen Wert verwirft, dann den rechten Operator auswertet und dessen Wert zurückgibt. Beispielsweise würde

    Quellcode

    1. a = (b = 2, b+3);

    der Variable a den Wert 5 zuweisen (mehr zu diesem Operator). In deinem Fall ist also lediglich der letzte Ausdruck

    Quellcode

    1. joint_index = new map<unsigned int,vector<double>* >()

    von Bedeutung. Es wird also nur dem member joint_index der pointer auf die neue map zugewiesen.
    Und wieso wurde nicht gemeckert, als ich auf x die Funktionen angewendet habe?

    Albert Einstein schrieb:

    Probleme kann man niemals mit derselben Denkweise lösen, durch die sie entstanden sind.
    Bist du dir sicher, dass es mit x funktioniert hat? Also hast du mal nur

    Quellcode

    1. x->insert(pair<...>(i,new vector<...>()));

    drin gelassen? Aber selbst wenn das ohne Absturz durchläuft, heißt das ja nicht, dass es so richtig ist. Es wird dann eben auf nicht reserviertem Speicher gearbeitet, was im weiteren Programmablauf zu seltsamem Verhalten oder einem Absturz führen kann.

    Bl@ckSp@rk schrieb:

    Bist du dir sicher, dass es mit x funktioniert hat? Also hast du mal nur

    Quellcode

    1. x->insert(pair<...>(i,new vector<...>()));

    drin gelassen?
    Sehr sicher. Ich bin ja gerade auf die Lösung gekommen, da ich es mit x und y durchgetestet habe. joint_index hab ich beim Probieren gar nicht angerührt.
    Naja, Hauptsache ich weiß jetzt woran es lag. Danke nochmal für die Hilfe, Bl@ckSp@rk!

    Albert Einstein schrieb:

    Probleme kann man niemals mit derselben Denkweise lösen, durch die sie entstanden sind.
    Ich bin's noch mal. Wollte nicht extra einen neuen Thread dafür aufmachen.
    Folgende Zeilen bescheren mir immer noch einen unexpected error:

    Quellcode

    1. double diff = (double)(j-prev);
    2. (*(this->x->find(i)->second))[j] = x_diff*diff;


    Was ist denn daran falsch? Ich finde bei Google einfach nicht die Lösung des Problems. Ich hab es mit ...second->at(j) auch probiert, und dort bekomme ich auch den selben Fehler. Auch wenn ich ohne Pointer arbeite bekomme ich den Fehler und wenn ich anstatt einer map einen vector aus vector nehmen, bringt das auch nichts.
    Wenn ich einen konstanten Wert zuweise (bspw. 0), dann gibt es keinerlei Fehler. Und der Compiler meckert auch nicht. Ich kann mir einfach nicht helfen. Entweder bin ich zu blöd oder einfach nur blind, was C++ angeht xD.

    [hide=Ganze Funktion]

    Quellcode

    1. for(int i = 0; i < this->get_bones(); i++){
    2. int prev = this->find_prev_keyframe(index);//Find previous keyframe
    3. int between = i-prev;//Calc frames between keyframes
    4. //Calc differences
    5. double x_diff = (this->x->find(i)->second->at(index)-this->x->find(i)->second->at(prev))/between;
    6. double y_diff = (this->y->find(i)->second->at(index)-this->y->find(i)->second->at(prev))/between;
    7. double angle_diff = (this->angle->find(i)->second->at(index)-this->angle->find(i)->second->at(prev))/between;
    8. double scale_diff = (this->scale->find(i)->second->at(index)-this->scale->find(i)->second->at(prev))/between;
    9. double parent_angle_diff = (this->parent_angle->find(i)->second->at(index)-this->parent_angle->find(i)->second->at(prev))/between;
    10. double parent_length_diff = (this->parent_length->find(i)->second->at(index)-this->parent_length->find(i)->second->at(prev))/between;
    11. double sprite_xscale_diff = (this->sprite_xscale->find(i)->second->at(index)-this->sprite_xscale->find(i)->second->at(prev))/between;
    12. double sprite_yscale_diff = (this->sprite_yscale->find(i)->second->at(index)-this->sprite_yscale->find(i)->second->at(prev))/between;
    13. double sprite_index_diff = (this->sprite_index->find(i)->second->at(index)-this->sprite_index->find(i)->second->at(prev))/between;
    14. double joint_xscale_diff = (this->joint_xscale->find(i)->second->at(index)-this->joint_xscale->find(i)->second->at(prev))/between;
    15. double joint_yscale_diff = (this->joint_yscale->find(i)->second->at(index)-this->joint_yscale->find(i)->second->at(prev))/between;
    16. double joint_index_diff = (this->joint_index->find(i)->second->at(index)-this->joint_index->find(i)->second->at(prev))/between;
    17. //Calc non-keyframe data
    18. for(unsigned int j = prev+1; j < index; j++){
    19. double diff = (double)(j-prev);
    20. (*(this->x->find(i)->second))[j] = x->find(i)->second->at(prev)+x_diff*diff;
    21. (*(this->y->find(i)->second))[j] = 0;//y->find(i)->second->at(prev)+y_diff*(j-prev);
    22. (*(this->angle->find(i)->second))[j] = 0;//angle->find(i)->second->at(prev)+angle_diff*(j-prev);
    23. (*(this->scale->find(i)->second))[j] = 0;//scale->find(i)->second->at(prev)+scale_diff*(j-prev);
    24. (*(this->parent_angle->find(i)->second))[j] = 0;//parent_angle->find(i)->second->at(prev)+parent_angle_diff*(j-prev);
    25. (*(this->parent_length->find(i)->second))[j] = 0;//parent_length->find(i)->second->at(prev)+parent_length_diff*(j-prev);
    26. (*(this->sprite_xscale->find(i)->second))[j] = 0;//sprite_xscale->find(i)->second->at(prev)+sprite_xscale_diff*(j-prev);
    27. (*(this->sprite_yscale->find(i)->second))[j] = 0;//sprite_yscale->find(i)->second->at(prev)+sprite_yscale_diff*(j-prev);
    28. (*(this->sprite_index->find(i)->second))[j] = 0;//sprite_index->find(i)->second->at(prev)+sprite_index_diff*(j-prev);
    29. (*(this->joint_xscale->find(i)->second))[j] = 0;//joint_xscale->find(i)->second->at(prev)+joint_xscale_diff*(j-prev);
    30. (*(this->joint_yscale->find(i)->second))[j] = 0;//joint_yscale->find(i)->second->at(prev)+joint_yscale_diff*(j-prev);
    31. (*(this->joint_index->find(i)->second))[j] = 0;//joint_index->find(i)->second->at(prev)+joint_index_diff*(j-prev);
    32. }
    33. int next = this->find_next_keyframe(index);
    34. if(next >= 0) this->calc_between(next);
    35. }

    [/hide]
    find_prev_keyframe und find_next_keyframe bringen keinerlei Probleme mit sich.

    Wär nett, wenn sich jemand melden würde.

    Edit: So wird die Funktion vom GM aus aufgerufen:
    [hide=Code]

    Quellcode

    1. gm double animation_calc_frames(double animation_index, double frame){
    2. if(animation_index >= 1 && animation_index <= anim_i){
    3. animations.find((unsigned int)animation_index)->second->calc_between((unsigned int) frame);
    4. return 1;
    5. }
    6. else return -1;
    7. }
    [/hide]

    Edit2: Hat sicher erledigt, der Name der externen Funktion wurde anscheinend falsch geschrieben. :headtouch:


    Edit3: Vergesst den letzten Edit, das Problem besteht weiterhin... -.-

    MfG

    Albert Einstein schrieb:

    Probleme kann man niemals mit derselben Denkweise lösen, durch die sie entstanden sind.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Trixt0r“ ()

    Ich vermute mal stark, dass du hier

    Quellcode

    1. (*(this->x->find(i)->second))[j]

    auf ein nicht existierendes Element zugreifst, also dass der vector nicht so viele Elemente enthält. Dann stürzt das Programm natürlich ab. Nimmst du für den Zugriff stattdessen die Methode at, so wird hingegen eine exception geworfen, welche in deinem Programm jedoch nicht abgefangen wird, was ebenfalls zu einem Absturz führt. Um zu testen, ob es wirklich am Zugriff auf ein nicht existierendes Element liegt, kannst du ja mal die out_of_range exception entsprechend behandeln.
    Die Vermutung hatte ich auch, aber das kann ja nicht sein, denn wenn ich z.B.

    Quellcode

    1. (*(this->x->find(i)->second))[j] = 0;

    dann gibt es keinen Fehler.
    Und die Maps und Vektoren werden ja im Konstruktor folgender Maßen initialisiert:

    [hide=Vorsicht]

    Quellcode

    1. x = new map* >();
    2. y = new map* >();
    3. angle = new map* >();
    4. scale = new map* >();
    5. parent_angle = new map* >();
    6. parent_length = new map* >();
    7. sprite_xscale = new map* >();
    8. sprite_yscale = new map* >();
    9. sprite_index = new map* >();
    10. joint_xscale = new map* >();
    11. joint_yscale = new map* >();
    12. joint_index = new map* >();
    13. this->keyframes = new vector();
    14. this->bones = bones;
    15. this->frames = frames;
    16. for(int i = 0; i < bones; i++){
    17. x->insert(pair* >(i,new vector()));
    18. y->insert(pair* >(i,new vector()));
    19. angle->insert(pair* >(i,new vector()));
    20. scale->insert(pair* >(i,new vector()));
    21. parent_angle->insert(pair* >(i,new vector()));
    22. parent_length->insert(pair* >(i,new vector()));
    23. sprite_xscale->insert(pair* >(i,new vector()));
    24. sprite_yscale->insert(pair* >(i,new vector()));
    25. sprite_index->insert(pair* >(i,new vector()));
    26. joint_xscale->insert(pair* >(i,new vector()));
    27. joint_yscale->insert(pair* >(i,new vector()));
    28. joint_index->insert(pair* >(i,new vector()));
    29. for(int j = 0; j < frames; j++){
    30. this->x->find(i)->second->push_back(0);
    31. this->y->find(i)->second->push_back(0);
    32. this->angle->find(i)->second->push_back(0);
    33. this->scale->find(i)->second->push_back(0);
    34. this->parent_angle->find(i)->second->push_back(0);
    35. this->parent_length->find(i)->second->push_back(0);
    36. this->sprite_xscale->find(i)->second->push_back(0);
    37. this->sprite_yscale->find(i)->second->push_back(0);
    38. this->sprite_index->find(i)->second->push_back(0);
    39. this->joint_xscale->find(i)->second->push_back(0);
    40. this->joint_yscale->find(i)->second->push_back(0);
    41. this->joint_index->find(i)->second->push_back(0);
    42. }
    43. }
    [/hide]
    Ich werde mir mal die out_of_range exception anschauen.
    Danke für die Antwort.

    Edit: out_of_range exception wird nicht geworfen, wenn ich ->at(j) benutze.

    Albert Einstein schrieb:

    Probleme kann man niemals mit derselben Denkweise lösen, durch die sie entstanden sind.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Trixt0r“ ()

    Gesagt, getan.

    Edit: Also ich kann mir das echt nicht erklären, denn wenn ich es in Netbeans teste, dann funktioniert die Funktion einwandfrei.

    Albert Einstein schrieb:

    Probleme kann man niemals mit derselben Denkweise lösen, durch die sie entstanden sind.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Trixt0r“ ()

    Also einen Fehler hab ich schonmal gefunden. Ob das der einzige Bug ist, ist eine andere Frage. Die Variable between in Animation::calc_between hatte bei meinen Tests den Wert 0 angenommen, was natürlich zu einem Absturz führt, da du später durch diese Variable teilst. Ich habe einfach mal probeweise die Variable between vor den ganzen Berechnungen auf 1 gesetzt, wodurch das Programm nicht mehr abgestürzt ist.
    Jop, das war der Fehler. Komisch, dass beim Testen in Netbeans nichts gesagt wurde. Anscheinend wird eine Division durch 0 dort abgefangen.
    Naja, hab die Bedingung der ersten for-Schleife angepasst.
    Vielen Dank, Bl@ckSp@rk, dass du dir die Mühe gemacht hast, meinen ekelhaften Code durchzulesen. ^^

    MfG

    Albert Einstein schrieb:

    Probleme kann man niemals mit derselben Denkweise lösen, durch die sie entstanden sind.
    Und es will einfach nicht aufhören mit den "unexpected errors" :headtouch: .
    Also diesmal ist der Fehler aber Game Maker spezifisch. Und zwar, wenn ich den Skript

    GML-Quellcode

    1. /*
    2. * Draws all bones with its sprites and joints of a given skeleton.
    3. *
    4. * argument0: skeleton_index;
    5. */
    6. var skel,i;
    7. skel = argument0;
    8. for(i = 0; i < bon_skeleton_get_bones(skel); i+=1){
    9. var bone;
    10. bone = bon_skeleton_get_bone_at(skel,i);
    11. if(sprite_exists(bon_bone_get_sprite(bone)) && sprite_exists(bon_bone_get_joint(bone))){
    12. var angle;
    13. angle = bon_bone_get_angle(bone);
    14. if(bon_bone_get_sprite_depth(bone) <= bon_bone_get_joint_depth(bone)){
    15. draw_sprite_ext(bon_bone_get_joint(bone),bon_bone_get_joint_image(bone),bon_bone_get_joint_x(bone),bon_bone_get_joint_y(bone),
    16. bon_bone_get_joint_xscale(bone),bon_bone_get_joint_yscale(bone),angle+bon_bone_get_joint_angle(bone),image_blend,image_alpha);
    17. draw_sprite_ext(bon_bone_get_sprite(bone),bon_bone_get_sprite_image(bone),bon_bone_get_sprite_x(bone),bon_bone_get_sprite_y(bone),
    18. bon_bone_get_sprite_xscale(bone),bon_bone_get_sprite_yscale(bone),angle+bon_bone_get_sprite_angle(bone),image_blend,image_alpha);
    19. }
    20. else{
    21. draw_sprite_ext(bon_bone_get_sprite(bone),bon_bone_get_sprite_image(bone),bon_bone_get_sprite_x(bone),bon_bone_get_sprite_y(bone),
    22. bon_bone_get_sprite_xscale(bone),bon_bone_get_sprite_yscale(bone),angle+bon_bone_get_sprite_angle(bone),image_blend,image_alpha);
    23. draw_sprite_ext(bon_bone_get_joint(bone),bon_bone_get_joint_image(bone),bon_bone_get_joint_x(bone),bon_bone_get_joint_y(bone),
    24. bon_bone_get_joint_xscale(bone),bon_bone_get_joint_yscale(bone),angle+bon_bone_get_joint_angle(bone),image_blend,image_alpha);
    25. }
    26. }
    27. else if(sprite_exists(bon_bone_get_sprite(bone)))draw_sprite_ext(bon_bone_get_sprite(bone),bon_bone_get_sprite_image(bone),bon_bone_get_sprite_x(bone),bon_bone_get_sprite_y(bone),
    28. bon_bone_get_sprite_xscale(bone),bon_bone_get_sprite_yscale(bone),bon_bone_get_angle(bone)+bon_bone_get_sprite_angle(bone),image_blend,image_alpha);
    29. else if(sprite_exists(bon_bone_get_joint(bone)))draw_sprite_ext(bon_bone_get_joint(bone),bon_bone_get_joint_image(bone),bon_bone_get_joint_x(bone),bon_bone_get_joint_y(bone),
    30. bon_bone_get_joint_xscale(bone),bon_bone_get_joint_yscale(bone),bon_bone_get_angle(bone)+bon_bone_get_joint_angle(bone),image_blend,image_alpha);
    31. }

    im Draw-Event eines Objektes ausführe, dann bekomme ich einen "unexpected error". Wenn ich allerdings eine Surface erstelle und das Skript im Step-Event auf die Surface anwende, wird ganz normal gezeichnet, so wie es sein soll.
    Also ich hab zumindest herausgefunden, dass der Fehler nach beliebig vielen Schleifendurchläufen eintritt (also der Crash tritt nach einem unbekannten Schema auf).
    Kann ich den Fehler irgendwie "einfach" umgehen oder bin ich jetzt gezwungen auf eine Surface zu zeichnen bzw. die Werte via ds_list oder array zu lesen?
    Hat der GM Probleme (so viele) externe Aufrufe auszuführen, wenn man sich im Draw-Event befindet?

    Albert Einstein schrieb:

    Probleme kann man niemals mit derselben Denkweise lösen, durch die sie entstanden sind.
    Hat der GM Probleme (so viele) externe Aufrufe auszuführen, wenn man sich im Draw-Event befindet?

    Nein, das hat mit großer Wahrscheinlichkeit nichts mit dem GM zu tun. Der Fehler liegt bestimmt irgendwo in der DLL (oder dort wo sie im GM aufgerufen wird). Du musst dich an diese "unexpected error" gewöhnen. Genauere Fehlermeldungen wirst du von einer DLL nicht bekommen. Musst dann halt debuggen um den Fehler einzugrenzen.
    Ich kann dir nur die Vollversion von VC++ ans Herz legen. Mit dieser kannst du DLLs debuggen, was auch perfekt mit GM-Spielen funktioniert.
    D.h. du startest dein Spiel, hängst die DLL an den Prozess an und kannst diese, wie ein normales C++ Programm debuggen. Unexpected Error? Darüber brauchst du dir dann keine Gedanken mehr machen, da du genaue Fehlermeldungen bekommst.

    © 2008 by Teamgrill Productions
    Konnte den Fehler beheben.
    Nachdem ich mir meine Daten erstellt habe, musste ich im GM einen Step warten, bevor ich anfangen konnte die Daten auszulesen. Das erklärt auch warum es im Step-Event funktioniert hat (glaube ich).
    @Soul Reaver Die Info hätte mir natürlich früher viel mehr genutzt. ^^ Aber danke für den Tip.

    MfG und gute Nacht!

    Albert Einstein schrieb:

    Probleme kann man niemals mit derselben Denkweise lösen, durch die sie entstanden sind.