Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

29.02.2012, 02:03

Ein neuer Anfänger im Forum quält Euch mit Fragen

Also erstmal Hallo @ Community. (Mein erster Beitrag )

Tja, der Erste Beitrag und Was sollte es anderes sein als ne Frage.
Da mein Wissensstand (gefühlt) jedoch in etwa gleich hoch ist wie die Beitragszahl (aktuell noch) bitte nicht zu sehr in die "Kiste" greifen.

Ich lese aktuell einige Bücher zum Programmieren in C++ und arbeite (noch) in der Konsole.

Hab folgendes Problemchen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <conio.h>
using namespace std;


// Würde ich in eine Header Datei packen (Test.h)
class C_Test{
protected:
    int m_Wert1;
    int m_Wert2;
public:
        C_Test();
        ~C_Test();
    void DatenAusgeben ();
};

// Würde ich in eine Quelltext datei schreiben (Test.cpp)

C_Test ::C_Test(){
    cout << "Konstruktor aufgerufen\n";
}

C_Test :: ~C_Test(){
    cout << "Destruktor aufgerufen\n";
}

void C_Test:: DatenAusgeben(){
    cout << "Datenausgabe\n";
}

// Hauptprogramm (sofern man dabei von "Programm" sprechen darf => dennoch Main.cpp

int main (void){

    int Wertarray;
    int Ausgabe;

    cout << "Wieviel instanzen?:\n";
    cin >> Wertarray;

    //Speicher freischaufeln
    C_Test *pZeiger = new C_Test[Wertarray];
    
    cout << "Nummer fuer Ausgabe:\n";
    cin >> Ausgabe;

    pZeiger[Ausgabe].DatenAusgeben();

    //Seicher freigeben
    delete[] pZeiger;
    pZeiger = NULL;

    _getch();
    return 0;
}


Als erstes wird auffallen, dass ich auf Kommentare fast zu 100% verzichtet hab. Erstens braucht ihr hier nicht nen "Anfängertext mit 100 // Zeilen" und 2tens muss ich hier ja nichts "wichtiges" hervorheben. Dennoch habe ich paar // gesetzt um diese gleich mal als Frage zu nehmen.

1.) Wäre eine Aufteilung in Datein (.h // . cpp) so richtig, oder müsste das anders aussehen? (klar ist das bei diesem Projekt mit der Pumpgun auf Spatzen, daher auch der Text in einem Aufguss)

und jetzt zum eigentlichen Problem.

2.)

Also wenn ich mich nicht irre, dann habe ich mit dem ersten abgefragten Wert einen Speicher (ja, ohne Prüfung ob verfügbar oder nicht und auch nicht mit Eingabekontrolle usw usw) am heap freigeschaufelt.
Habe also ein Array mit X Instanzen der Klasse C_Test erzeugt.

Okay..

Wenn ich aber nu hergehe und den 2ten abgefragten Wert >= dem ersten mache (also 10 instanzen, aber ausgabe 45 von mir aus) müsste ich doch normal auf einen Speicher zugreifen der gar nicht belegt sein kann (von mir), oder? Dennoch ist es so, dass wenn ich diesen Code compiliere, dass ich keinerlei Fehlermeldungen erhalte und auch die Ausgabe von wegen "Datenausgabe" immer am Bildschirm erscheint, auch wenn der Bereich nicht von mir reserviert wurde.

Gott bin ich mies im erklären... Bildschirmausgabe hilft :)

Zitat

Wieviel Instanzen?:
3
Konstruktor aufgerufen
Konstruktor aufgerufen
Konstruktor aufgerufen
Nummer fuer Ausgabe:
20
Datenausgabe
Destruktor aufgerufen
Destruktor aufgerufen
Destruktor aufgerufen
Vllt erklärt das Verhalten des "Programms" das ganze ein bisschen besser als ich :love:
Müsste da kein fehler auftauchen, oder hab ich einfach nur Glück oder oder oder...

Ich sag jetzt schonmal DANKE für eventuelle Antworten

LG

Amico (Anfänger der gern mehr wissen würde) :)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

29.02.2012, 02:24

1.) Wäre eine Aufteilung in Datein (.h // . cpp) so richtig, oder müsste das anders aussehen? (klar ist das bei diesem Projekt mit der Pumpgun auf Spatzen, daher auch der Text in einem Aufguss)

Sieht vernünftig aus.

Wenn ich aber nu hergehe und den 2ten abgefragten Wert >= dem ersten mache (also 10 instanzen, aber ausgabe 45 von mir aus) müsste ich doch normal auf einen Speicher zugreifen der gar nicht belegt sein kann (von mir), oder?

exakt

Dennoch ist es so, dass wenn ich diesen Code compiliere, dass ich keinerlei Fehlermeldungen erhalte und auch die Ausgabe von wegen "Datenausgabe" immer am Bildschirm erscheint, auch wenn der Bereich nicht von mir reserviert wurde.

Der Compiler kann weder wissen, wie groß Wertarray zur Laufzeit sein wird, noch kann er wissen, welchen Wert Ausgabe bekommen wird. Je nachdem was der Benutzer eingeben wird, wird das Programm funktionieren oder nicht, der Compiler kann das beim Kompilieren nicht entscheiden.

Müsste da kein fehler auftauchen, oder hab ich einfach nur Glück oder oder oder...

Du hast einfach nur Glück. Oder auch Pech, je nachdem wie man's sieht (die Tatsache dass das Programm nicht abstürzt, ist nicht unbedingt positiv, da der Fehler so möglicherweise unbemerkt bleibt).
Es ist eben sog. "undefiniertes Verhalten", d.h. es gibt keine Garantie was genau passieren wird. Nichts ist genauso eine Möglichkeit wie rosa Ponys.
In C++ liegt es in der Verantwortung des Programmierers, sicherzustellen, dass sowas nicht passiert.
Manche andere Sprachen überprüfen automatisch, ob Arraygrenzen überschritten werden. In C++ muss man sich darum selbst kümmern, wenn man es haben will (diese Überprüfungen erzeugen natürlich einen kleinen Overhead und eine Grundphilosophie von C++ ist "you don't pay for what you don't use").
Anstatt eines rohen Arrays könntest du natürlich std::vector aus der Standardbibliothek verwenden. Die at() Methode des vector führt einen range check durch.

Aber natürlich gibt es eine einfache Erklärung dafür, dass hier nichts passiert: Da deine Methode DatenAusgeben() auf keine Member der Klasse zugreift, wird natürlich auch nirgendwo auf den nicht vorhandenen Speicher zugegriffen und daher passiert auch nichts. Würdest du dort z.B. m_Wert1 ausgeben, dann würde das Programm entweder abstürzen (Access Violation), oder Müll ausgeben (was auch immer dort grad zufällig im Speicher steht).

Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von »dot« (29.02.2012, 02:38)


3

29.02.2012, 02:46

Suuper Erklärung und herzlichen Dank für die rasche Antwort.

Ja, Auf die eigentlichen Member greife ich ja über meine ZeigeDaten() nicht zu. Somit erklärt sich mein "Glück" :)
Das mit den Vektoren werde ich mir gleich mal angucken. Es schadet nicht Baustellen von 2 Seiten zu bearbeiten solange man sich inner Mitte treffen kann.

Also nochmal herzlichen Dank und hier fühl ich mich wohl, hier quäle ich weiter :)


Amico

Werbeanzeige