Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (WinAPI, Konsole) » C++ Runtime Environment unter Vista?

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
31.01.2009, 23:29 Uhr
~Dengue
Gast


Hallo,
ich habe mal wieder seit einiger Zeit ein kleines Projekt in C++ geschrieben. Diesmal allerdings unter Vista. Ich habe dev C++ dafür genutzt.
Kurz bevor ich mein Programm fertiggestellt habe, ist es zu einem Laufzeitfehler gekommen, den ich mir nicht erklären kann: ich habe eine Struktur angelegt und dann entsprechende Objekte im Main-Programm erstellt.
Hier ein Quellcode-Ausschnitt von meinen Deklarationen:


C++:
int main(int argc, char *argv[])
{    
    stack *anker = NULL;

    char *eingabe;

    stack *p;

    char operationen[9][5] = {{"+"},{"-"},{"*"},{"/"},{"abs"},{"neg"},{"inv"},{"sqr"},{"sqrt"}};



Damit läuft das Programm.


C++:
int main(int argc, char *argv[])
{    
    stack *anker = NULL;

    stack *p;

    char *eingabe;

    char operationen[9][5] = {{"+"},{"-"},{"*"},{"/"},{"abs"},{"neg"},{"inv"},{"sqr"},{"sqrt"}};



Damit läuft es nicht. Sobald ich bei dem Pointer p und eingabe die Deklarationsreihenfolge ändere, kommt es zur Laufzeit mitten im Programm wahrscheinlich zu einem Speicherfehler und es schmiert ab.
Auch wenn ich nicht weiß wieso, habe ich mich damit abgefunden. Das nächste ist jetzt aber, dass ich einem Freund, der jetzt auch das "gute" Vista auf seinem Laptop hat, die funktionierende .exe (also die Deklaration in der funktionierenden Reihenfolge) geschickt habe. Obwohl es bei mir läuft, schmiert es bei ihm ab. Nur unter XP läuft es bei ihm.
Dann hat er mir ein Projekt, welches er in C und ohne spezielle Funktionen geschrieben hat, geschickt und Vista meldet bei mir, dass eine DLL fehlt. Mein Kumpel hat aber auch keine DLLs eingebunden.

Irgendwie scheint es da Probleme mit der C++ Runtime Environment für Vista zu geben, oder sehe ich das falsch? Es kann doch nicht sein, dass wir gegenseitig unsere Programme, die nur einfachste Ein- und Ausgaben, sowie nur ein paar mathematische Operationen beeinhalten, nicht mehr ausführen können.
Kennt Ihr die Probleme und vielleicht auch eine Lösung?

MfG
Dengue
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
31.01.2009, 23:40 Uhr
Guybrush Threepwood
Gefürchteter Pirat
(Operator)


Klar wenn ein Fehler im eigenen Programm auftritt ist ein Bug in der C Runtime


Aber mal ernsthaft, das da eine bei dir geht und das andere nicht ist einfach Glück. Irgendwo in deinem Programm hast du einen odere mehrere Fehler wo du in Speicher schreibst in den du nicht schreiben solltest bzw. über Feldgrenzen hinweg. Vielleicht klappt ersteres weil da noch das char* vor deiner Struktur im Speicher liegt, aber das kann man nicht sagen.


Zweiteres wird daran liegen das dein Freund wahrscheinlich eine andere Entwicklungsumgebung genommen hat wie du und das wäre auch gut so, denn Dev C++ solltest du so schnell wie möglich los werden weil der vebuggt und veraltet ist und schon seid langém niemand mehr daran arbeitet. Leider wird er aber trotzdem noch immer wieder von Anfängern empfohlen...

Dieser Post wurde am 31.01.2009 um 23:41 Uhr von Guybrush Threepwood editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
31.01.2009, 23:59 Uhr
0xdeadbeef
Gott
(Operator)


Naja, Dev-C++ ist ne beschissene IDE, aber im Backend benutzt sie den GNU-Compiler. Auch wenn möglicherweise eine alte Version beiliegt, dass der zufällig Speicherfehler einbaut, kann ich mir nun wirklich nicht vorstellen.

Ansonsten hat Guybrush aber recht, das Programm wird irgendwo undefiniertes Verhalten erzeugen, höchstwahrscheinlich ein wilder Zeiger, ein Buffer-Overflow oder etwas in der Art. Wenn du eine UNIX- oder Linux-Maschine zur Hand hast, lass mal valgrind drüberlaufen, der wird dir wahrscheinlich einiges dazu ausspucken. Falls nicht, nimm Knoppix, da sollte valgrind dabei sein.

Ansonsten, warum benutzt du als Stack nicht std::stack? Jetzt unter der Annahme, dass "stack" ein Stack ist.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 31.01.2009 um 23:59 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
01.02.2009, 00:17 Uhr
~Dengue
Gast


Erstmal danke für die Antworten.
Normalerweise nutze ich Visual C++. Da ich aber gerade für längere Zeit nicht zu Hause bin und es auch nicht auf meinem Laptop habe, habe ich mir halt dev C++ gezogen.
Wenn es sich um einen Programmierfehler meinerseits handelt, warum macht es dann einen Unterschied, in welcher Reihenfolge ich die Variablen deklariere, wenn sie eh nicht voneinander abhängig sind?
Übrigens handelt es sich bei der Struktur stack um eine verkettete Liste, die laut Aufgabenstellung so heißen soll.

MfG
Dengue
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
01.02.2009, 02:11 Uhr
0xdeadbeef
Gott
(Operator)


Grundsätzlich bedeutet undefiniertes Verhalten, dass alles mögliche passieren kann; in diesem Fall ist davon auszugehen, dass es davon abhängt, wie der Compiler den Speicher verwaltet. Das ist etwas, was sich besser mit Papier und Stift erklären lässt, aber ich versuch mal mein bestes. Nehmen wir einen einfachen Fall:

C++:
int main() {
  int x = 0, y = 1;
  int a[5];

  a[5] = 3; // Buffer-Overflow!
  y = 4;
}


Wenn der Compiler das wie folgt auf den Stack legt (weiter rechts = höhere Speicheradresse):

Code:
| a[0]| a[1]| a[2]| a[3]| a[4]| y  | x  |


...also stumpf in der Reihenfolge pusht, in der der Kram im Sourcecode auftaucht, dann ist &a[5] == a + 5 == &y, also ist a[5] = 3; im Effekt das selbe wie y = 3;, und weil danach y = 4; gesetzt wird, ist es im Grunde so, als würde a[5] = 3; nie ausgeführt.

Wenn der Compiler aber zum Beispiel Deklarationen a la int x, y; umgekehrt behandelt und der Stack aussieht wie folgt:

Code:
| a[0]| a[1]| a[2]| a[3]| a[4]| x  | y  |


...dann ist a[5] = 3; das selbe wie x = 3;, und das macht sich dann bemerkbar.

Noch gemeiner wird es natürlich, wenn du nicht mal in andere Variablen, sondern in Steuerbereiche schreibst, zum Beispiel in Rückgabewerte oder Rücksprungadressen. Insbesondere letzteres ist übrigens ein beliebtes Einfallstor für Schadsoftware.

Ein anderer Fall:

C++:
deine_klasse *foo() {
  deine_klasse *p = new deine_klasse();

  return p;
}

andere_klasse *bar() {
  andere_klasse *p; // Initialisierung vergessen!

  if(std::rand() % 2 == 0) {
    p = new andere_klasse();
  }

  return p;
}

int main() {
  deine_klasse *d;
  andere_klasse *a;

  d = foo();
  a = bar();

  // Irrige Annahme, dass bar() NULL zurückgebe
  if(ptr) {
    a->methode();
  }

  delete d;
  delete a;
}


In diesem Fall kann es passieren, dass beim Aufruf von bar() der Stack genau an der selben Stelle aufgerollt wird wie beim Aufruf vom foo() und p in bar() an der selben Stelle liegt wie beim Aufruf vom foo(). In dem Fall ist in main nachher d == a, und a->methode() ist das selbe wie reinterpret_cast<andere_klasse*>(d)->methode(), was wieder ein ganz anderes Wespennest ist. Genausogut kann es aber sein, dass der Optimizer p in foo() wegoptimiert und a nachher ins Nirvana zeigt.

Das sind jetzt nur zwei aus einer ganzen Latte möglicher Speicherfehler. Was bei dir genau passiert, kann ich natürlich nicht beurteilen, in jedem Fall lohnt es sich aber, mit seinem Speicher vorsichtig umzugehen.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 01.02.2009 um 02:12 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
01.02.2009, 12:55 Uhr
~Dengue
Gast


Wow, vielen Dank für die ausführliche Erklärung. Dein Beispiel mit a[5]=3 müsste ja eigentlich schon vom Compiler verhindert werden, weil er ja erkennt, ob das Array mit 5 oder 6 Elementen deklariert wurde.
Bei meinem Programm trifft dann eher dein zweites Beispiel zu: ich initialisiere nicht alle Pointer, wobei ich diese aber auch zur Laufzeit erst mit einer gültigen Adresse beschreibe und dann auslese.
Aber ich denke trotzdem, dass irgendwie bei der Deklaration in den Speicherbereich des char-Arrays Operationen geschrieben wird, weil nämlich beim Auslesen dieses Arrays in einer Schleife neben dem eigentlichen Inhalt noch wirrer Speicherinhalt ausgegeben wird. Dann kommt es zum Absturz. Ich denke, dass versucht wird auf einen Speicherbereich eines anderen Programm zuzugreifen, was ja das OS eigentlich verhindert.
Es ist natürlich scheisse, wenn ein solch einfaches Programm nicht auf allen Rechnern läuft.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
01.02.2009, 15:42 Uhr
0xdeadbeef
Gott
(Operator)


Ein Compiler sollte in einem so offensichtlichen Fall mindestens warnen, ja. Es war aber auch nur ein Beispiel, denk dir ggf. halt noch eine Indexeingabe aus einer Datei oder von der Konsole dazu. Ich hielt es so für einfacher als

C++:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <iostream>
#include <string>

int main() {
  pid_t pid;
  int status;
  int pipes[2];

  pipe(pipes);
  pid = fork();

  if(pid == -1) {
    std::cerr << "Fehler beim Forken!";
  } else if(pid == 0) {
    close(STDOUT_FILENO);
    dup(pipes[1]);
    close(pipes[0]);

    std::cout << "5" << std::endl;
  } else {
    int i;
    int x = 1, y = 2, a[5];

    close(STDIN_FILENO);
    dup(pipes[0]);
    close(pipes[1]);

    std::cin >> i; // i ist jetzt 5

    a[i] = 3;
    y = 4;

    waitpid(pid, &status, 0);
  }
}



Was bei dir passiert, kann ich nicht beurteilen, zumal es ja kein Bohr-Bug ist. Wenn noch wirrer Kram ausgegeben wird, kann das darauf hindeuten, dass irgendwo ein Null-Terminator fehlt, aber das ist jetzt ein Schuss ins Blaue (und geht davon aus, dass du unweiserweise C-Strings in C++ benutzt).
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (WinAPI, Konsole) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: