Probleme bei struct-Benutzung

sTEk

Erfahrenes Mitglied
Probleme bei struct-Benutzung & new

Hallo!
Ich habe Probleme bei der Verwendung einer struct-Anweisung. Diese habe ich als Member-Variable in der Headerdatei meiner Klasse deklariert
Code:
// Dialogfeld CCOMDialog 
      
      class CCOMDialog : public CDialog
      {
      // Konstruktion
      public:
      		BYTE    m_tataa[263000];
  		  struct Header
      			{
 			unsigned EELow		:	 8;
 			unsigned EEHigh		:	 8;
 			unsigned KabNumb	:	13;
 			unsigned EENumb		:	 3;
      			};
      
      		Header	m_Kopf[1004];
- es funktioniert auch, solang ich den Code, der diese Werte beschreiben soll in einer Funktion wie OnButton() nutze.

Da ich diesen Code jedoch an mehreren Stellen benötige, wollte ich ihn als extra Funktion in meiner Klasse bereitstellen:
Header-Datei
Code:
protected:
     
     	// Generierte Nachrichtenzuordnungsfunktionen
     	//{{AFX_MSG(CCOMDialog)
     
     	afx_msg int CCOMDialog::HeaderLesen();
CPP-Datei
Code:
int CCOMDialog::HeaderLesen()
     {		int		j,st;
     		char	buffer[100];
     
 				for (j=0; j<4000; j=j+4) {
     			st++;
     			m_Kopf[st].EENumb = m_tataa[j];
      			m_Kopf[st].KabNumb = m_tataa[j+1];
      			m_Kopf[st].EEHigh = m_tataa[j+2];
      			m_Kopf[st].EELow = m_tataa[j+3];
      			return st; }

Wenn ich nun int anzahl=HeaderLesen(); aufrufe bricht mein Program leider mit einer Fehlermeldung über einen fehlerhaften Speicherzugriff, "read" konnte nicht auf Adresse 0xblabla ausgeführt werden. Was habe ich vergessen bzw. vermasselt?
An der Variablendeklaration kann es nicht leigen, die funktioniert so ja einwandfrei... :/
 
Zuletzt bearbeitet:
Hi,
Erzetze mal die erste Zeile deiner CPP
Code:
int j,st;
mit
Code:
int j,st = 0;
uninitialisiert ist es schlecht, du weisst nie ob st am Anfang wirklich 0 ist.
 
Ich danke Dir, genau das wars...manchmal muss ich mir selbst 'ne Ohrfeige geben - gerade weil ich das int st=0; im "Original-Versuchs-Quelltext" noch drin hatte....

DANKE! :)
 
Böse 1: Wie PixelShader gesagt hat -> st ist unizialisiert!

Böse 2: Dein Klassenmembers: BYTE m_tataa[263000]; ist ein wenig pervers (sorry für den Ausdruck). Das sind über 256 Kb. Wenn jetzt eine Instanz deiner Klasse auf dem Stack erstellt wird, dann ist das etwas übertrieben, bitte nicht soviel statischen Speicher reservieren, das führt zu Problemen.
Bitte setze dich mit dynamischer Speicherverwaltung unter C++ bzw, C auseinander (Stichworte: new, delete, malloc, free, usw...)

Gruß Daniel
 
@Daniel
Danke für Deine Tipps. Ich habe mich mal zum Thema new und delete belesen. Wenn ich für mien Beispiel die dynamische Verwaltung so induziere
Code:
BYTE* m_tataa = new BYTE[263000];
verstehe ich jedoch nicht, welchen Vorteil mir das bringt. Ich muss doch trotzdem die Anzahl der Elemente angeben (es sind nun mal so viele) - habe ich jedenfalls so raus gelesen.

Eine weitere Frage:
Wenn ich jetzt nicht weiß, wie viele Elemente ich in einer Matrix habe, also, der erste Wert ist fest - sagen wir mal 1000 - und der zweite Wert variiert - zwischen 0 und 90000 - wie kann ich das sinnvoll umsetzen?
 
Hi!

Der Unterschied der Deklarationen
Code:
struct XXX a[n];
und
Code:
struct XXX *a = new XXX[n];
ist folgender:
Bei der ersten Variante wird der Speicher auf dem Stack abgelegt, der eine BEGRENZTE Größe hat.
Der Stack wird unter anderem für Rücksprungadressen bei Unterprogrammaufrufen, Parameter und lokale Variabeln der verwendet.
Mit deiner Deklaration belastest du den Stack unnötig und zwar ganz gewaltig:

1. Es bleibt weniger Speicherplatz für evtl. Rücksprungadressen etc.
2. Stell dir mal vor du übergibst diese Struktur als Parameter oder gibst sie als Ergebnis einer Funktion zurück. Es würde eine Kopie mit der gleichen Größe auf dem Stack angelegt und somit doppelt Speicherplatz verschwendet.
(ok, bei Parametern besser Referenzen oder Zeiger....)

Bei der zweiten Variante wird der Speicher vom sogenannten Heap bereitgestellt, der meines Wissens nach nur durch die Größe des verfügbaren Arbeitsspeichers begrenzt ist.
Wenn du das so löst, muss immer nur der Zeiger auf den Anfang des Speicherblocks auf den Stack und das bei gleicher Benutzung.

Das Einzige was sich wirklich ändert: Du musst den angeforderten Speicher wieder freigeben:
Code:
delete[] a; // [] weil du mit new einen Array angefordert hast

Ich hoffe das hat dir geholfen... :-)

Gruß
Johannes
 
Möchte auch meinen Senf dazu geben!

Du hast m_Kopf mit 1004 Elementen deklariert, deine Schleife geht aber bis 4000. Das kann auch ganz schnell (je nach Prozessor) in die Hose gehen :)
 
Ich fange an diese Sprache zu hassen....irgendiwe klappt nichts so wie es im Buch steht...

Jetzt wollte ich wie hier vorgeschlagen eine dynamische Speicherzuweisung machen:
Code:
	BYTE* m_tataa;
  	m_tataa=new BYTE[262144];

Tja...da bringt mir der Compiler folgendes:
:\c++\a3\comdialog.h(22) : error C2258: Ungueltige Syntax fuer rein virtuelle Methode; '= 0' erforderlich
d:\c++\a3\comdialog.h(22) : error C2501: 'm_tataa' : Fehlende Speicherklasse oder Typbezeichner


Was um himmels Willen hab ich jetzt wieder verkehrt gemacht? Wenn ich statt BYTE int oder char nehme passiert das gleiche. :(

Nachtrag:
Ich habe die Anweisungen in der Header-Datei unter public stehen - dort wo auch die anderen Membervariablen deklariert sind.
 
Zuletzt bearbeitet:
Hi,

was du gemacht hast ist abstrakt gesehen folgendes:
Code:
class XXX
{
    TYP m_member; // Das ist ok: Deklaration eines Datenmembers
    TYP f1(); // Das ist auch ok: Deklaration einer Memberfunktion
    TYP f2(TYP value)
    {
        m_member = value;
    } // Das ebenfalls: Deklaration und Definition einer Memberfunktion

    int a = 0; // Das ist tödlich: Ausführbarer Code direkt in einer Klassenvereinbarung
};
Such mal nach Lebenszyklus von Objekten, Konstrukor, Destruktor.

Dann wird dein Code von der Struktur her so aussehen:
Code:
class XXX
{
    TYP *m_member; // ein Datenmember (Zeiger auf TYP)
    
    XXX()
    {
        m_member = new TYP[N]; // Speicher wird beim Konstruieren des Objektes angefordert...
    } // Konstruktor

    ~XXX()
    {
        delete[] m_member; // ...und beim Destruieren wieder freigegeben
    }
};


Gruß
Johannes

PS: private, public protected hab ich aus Gründen der Übersicht weggelassen!
 
Zuletzt bearbeitet:
Zurück