Segmentation fault
-
Hallo zusammen!
Ich arbeite seid ca. 3 Monaten mit C++ und es klappt eigentlich auch schon ganz gut, aber jetzt bin ich an meine Grenzen gestossen. Es geht um flogendes Teilprogramm:#include <stdio.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> #include"bamatrix.h" int build(Matrix<int>*& v, Matrix<int> Cluster, Matrix<int> Coordinates, int index) //hier wundert mich schon, dass ich "Matrix<int>*& v" und nicht "Matrix<int>* v" uebergeben muss - aber das ist nicht das Problem :) { int sumclustersize = 0; Matrix<int> matrix; Matrix<int>* ve = (Matrix<int>*)malloc(index*sizeof(Matrix<int>)); for(int t = 0; t < index; t++) { int j = 0; for(int i = sumclustersize; i < sumclustersize+Cluster[t][3]; i++) { matrix.resize(Cluster[t][3],2); matrix[j][0] = Coordinates[i][0]; matrix[j][1] = Coordinates[i][1]; j++; } j = 0; sumclustersize = sumclustersize+Cluster[t][3]; ve[t] = matrix; // hier ist das Problem !!! Obwohl ich ve "gross" genug definiert habe, bekomme ich irgendwann einen Segmenterror } v = ve; // fragt mich nicht, warum die Matritzen nicht direkt in v schreiben kann - sonst funktioniert es gar nicht. }**
Fehlermeldung mit DGB:**
Program received signal SIGSEGV, Segmentation fault.
0x0804f57e in _Vector_impl (this=0x2, __a=@0xbffe7280)
at /usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stl_vector.h:85
85 { }Beschreibung des ganzen Programms
Ich starte mit einer Null-Matrix und verteile dann zufaellig eine gewisse Anzahl Einsen (Teilchen) auf der Matrix. Teilchen die sich rechts, links, oben oder untern beruehren bilden eine Einheit (Cluster). Danach waehle ich einen beliebigen Cluster und bewege ihn in eine der 4 Richtungen. Danach testet das Programm ob der Cluster "Nachbar" eines weiteren Clusters geworden ist und verbindest diese gegebenenfalls. Dies fuehre ich solange fort, bis ich nur noch einen grossen Cluster habe.Beschreibung des Problems
In dem header "build" will ich einen Vektor "v" erzeugen, der als Eintraege alle derzeit vorhandenen Cluster (also Matritzen) enthaelt. Die Matrix "Cluster" enthaelt in der ersten bzw zweiten Spalte die x- bzw y-Koordinate eines Teilchens eines jeden Clusters und in der dritten Spalte die "Groesse" (Anzahl der Teilchen) des Clusters. In der Matrix Coordinates speichere ich die derzeitigen Koordinaten saemtlicher Teilchen. Wenn also zum ersten Cluster (erste Zeile in Matrix "Cluster") 10 Teilchen gehoeren, dann stehen in den Eintraegen 0-9 der Matrix "Coordinates" alle Teilchen des ersten Clusters. Jetzt moechte ich diese Information als Matrix abspeichern und in v[0] ablegen, den 2. Cluster dann in v[1] usw. Das komische ist nun, dass es einwandfrei funktioniert, wenn die Startmatrix (auf der die Teilchen alle liegen) nicht groesser als 250x250 ist, sobald ich aber groesste Matritzen ausprobiere, beikomme ich den oben angezeigten Fehler.Danksagung

So ich hoffe es kann mir jemand helfen - ich weiss mit meinen beschraenkten Mitteln naemlich wirklich nicht mehr weiter. Und seid nicht zu hart zu mir, falls ich einen Anfaengerfehler gemacht habe - ich bin naemlich einer :). Schon mal vielen Dank im Voraus - ausdruecklich auch wenn du dies "nur" gelesen hast, aber mir nicht weiterhelfen konntest.
-
malloc + c++ objekte = boom
-
Um es ein wenig genauer zu machen. Du kannst beim dynamischen Erzeugen von Klasseninstanzen kein malloc verwenden, da hierbei keine Konstruktoren aufgerufen werden. Nimm new und es sollte gehen.
-
vielen Dank Jungs!! Hab es schon hinbekommen. Nur falls nocheinmal jemand anderes das gleiche Problem hat - sozusagen fuer die Statistik :):
Matrix<int>* ve = new Matrix<int>[index];-CLOSE-
-
Ich hoffe du hast dann auch das richtige delete genommen.

-
Um es ein wenig genauer zu machen.. :p
delete[]
-
Ok, jetzt bin ich dummerweise wieder in einer Sackgasse. Problem ist noch wie oben. Ich will ein Array von Matritzen erzeugen. Mit
Matrix<int>* Store = new Matrix<int>[index];
hat das wunderbar geklappt - zumindest solange ich die Groesse des Vektors kenne. Leider muss ich diesen jetzt erweitern/verlaengern.
Wenn ich normal Matrizen habe, funktioniert das wunderbar mit Store.resize(x,y). Leider sollte das hier nicht klappen. Hat einer eine Idee? Schon mal vielen Dank fuer die erneute Hilfe
-
Lagrange schrieb:
Ok, jetzt bin ich dummerweise wieder in einer Sackgasse. Problem ist noch wie oben. Ich will ein Array von Matritzen erzeugen. Mit
Matrix<int>* Store = new Matrix<int>[index];
hat das wunderbar geklappt - zumindest solange ich die Groesse des Vektors kenne. Leider muss ich diesen jetzt erweitern/verlaengern....
Dann mach es nicht selbst, sondern nimm die Standardmittel dafür: std::vector
Dann sieht das so aus:
std::vector<Matrix<int> > Store(index); // Achtung: Leerzeichen bei "> >" ist wichitgEinzelne Elemente hinzufügen kannst Du mit push_back()...
Und deleten brauchst Du auch nichts mehr.Alternativ kannst Du natürlich das Rad neu erfinden und Dich mit einer Menge Segfaults rumschlagen

Gruß,
Simon2.
-
Hallo!
Ups, da liegt glaub ich einiges im Argen:
-
Du musst die Zeigerreferenz übergeben da ansonsten malloc() oder new() an eine temporäre Kopie zuweisen würden - nämlich an ein long das auf dem Stack liegt und den alten Wert des (NULL ?) - Zeigers enthält.
-
[index] meint doch eher [size], oder?
-
Ist Matrix eigentlich eine class oder ein struct?
Was build() macht scheint mir in einen benuzerdefinierten Matrix-Konstruktor zu passen. -
Wieso wählst Du diese Strategie zur Einrückung?
Stroustrups Konvention sieht völlig anders aus und ist imo viel besser zu lesen.
Solch kmplizierte Zeigerarithmetik muss optisch gut dargestellt werden.
- Probleme bei 250*250 sind wohl eher Probleme bei 256*256 was 2^16 = 65536 enspricht. Also irgendwas bei 64k. Bei der Hausnummer gab's schon oft Probleme.
=> Wie ist Matrix intern aufgebaut ? <=
- vector< vector<T> >
- T[][]Vorsicht!
T[][] ist KEIN T** ! Stroustrup C++PL §C.7.3 - da geht's um Matrizen

- Teilchen als 1/0 ist ja (noch) boolean, bleibt das so?
Wenn ja : Du bildest es auf ein int ab. Hast Du Dich mal mit <bitset> befasst ? Es könnte eine effiziente Implemntierung damit geben.
Grüsse
*this
-
-
Vielen Dank!
Ich haette nicht gedacht, dass es so einfach ist
- warum komme ich auf sowas nie selbst :). Simons2s Vorschlag funkioniert einwandfreiAuch vielen Dank an Gast++ - leider bin ich fuer deine Antwort noch zu dumm, werde sie aber auf jeden Fall nochmal in Ruhe durchlesen und versuchen zu verstehen. Ein Glueck tut es wie gesagt schon der Ansatz von Simon

-
@Gast++
zu 1.
Bei der einfachen Ereugung mit new braucht man keine Zeigerreferenz. Das brauchst du dann eher wenn du dieses in eine Funktion asulagerst. malloc hat hier eh nichts zu suchen da dort keine Konstruktoren aufgerufen werden. Es sei denn du bastelst dir hier was mit einem placement new zusammen was hier aber gar nicht nötig ist.
zu 3.
Wasc machst das für einen Unterschied ob es eine class oder eine struct ist? Die werden beide gleich behandelt.
-
Braunstein schrieb:
@Gast++
zu 1.
Bei der einfachen Ereugung mit new braucht man keine Zeigerreferenz. Das brauchst du dann eher wenn du dieses in eine Funktion asulagerst.Ja, und der Zeiger um den es geht ist ein formaler Parameter der build Funktion.
Lies bitte mal die Zeilenendkommentare im OP.Braunstein schrieb:
malloc hat hier eh nichts zu suchen da
Das war bereits erklärt worden; hier gings um die Übergabe der Zeigerreferenz.
Braunstein schrieb:
dort keine Konstruktoren aufgerufen werden. Es sei denn du bastelst dir hier was mit einem placement new zusammen was hier aber gar nicht nötig ist.
zu 3.
Wasc machst das für einen Unterschied ob es eine class oder eine struct ist? Die werden beide gleich behandelt.Dann zeig mir doch bitte mal einen "struct-Konstruktor" mit ctor Semantik.

Grüsse
Gast++
-
Gast++ schrieb:
Braunstein schrieb:
dort keine Konstruktoren aufgerufen werden. Es sei denn du bastelst dir hier was mit einem placement new zusammen was hier aber gar nicht nötig ist.
zu 3.
Wasc machst das für einen Unterschied ob es eine class oder eine struct ist? Die werden beide gleich behandelt.Dann zeig mir doch bitte mal einen "struct-Konstruktor" mit ctor Semantik.

Grüsse
Gast++
Aus C++ Sicht gibt es nur einen Unterschied zwischen 'struct' und 'class' - struct-Elemente sind per Default public, class-Elemente private. Ansonsten sind beide völlig identisch.
(insbesondere kann ein struct auch Memberfunktionen, private Member (mußt du explizit angeben) und sogar Ctor'en haben)
-
CStoll schrieb:
Aus C++ Sicht gibt es nur einen Unterschied zwischen 'struct' und 'class' - struct-Elemente sind per Default public, class-Elemente private. Ansonsten sind beide völlig identisch.
(insbesondere kann ein struct auch Memberfunktionen, private Member (mußt du explizit angeben) und sogar Ctor'en haben)Danke für den Hinweis!
Das ändert aber nichts daran dass die freie "build"-Funktion Aufgaben wahrnimmt die gut in einen Konstruktor passen würden.
Auch in einen struct-Konstruktor.Grüsse
Gast++
-
Ich stoere ja nur ungerne euere Fachsimpelei - von der ich btw kein Wort verstanden habe
- aber bezog sich ja auch ein Glueck nicht mehr richtig auf mein Problem.Auf jeden Fall klappt die ganze Sache doch noch nicht so wirklich. Ich habe das gestern mal schnell mit einem kleinen Testprogramm getestet. Einwandfrei funktioniert:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> #include"bamatrix.h" int main() { int index = 0; Matrix<int> M(2,2); std::vector<Matrix<int> > Store(index); for(int i = 0; i<4; i++) { M[0][0] = i; M[0][1] = i; M[1][0] = i; M[1][1] = i; Store.push_back(M); } Matrix<int> K(2,2); K = Store[3]; cout << K[1][1] << endl; }Aber sobald ich es in ein groesseres Programm einbaue, bekomme ich beim ausfuehren von
std::vector<Matrix<int> > Store(index);flogende Fehlermeldung (mit der man natuerlich wieder unglaublich viel anfangen kann): *** glibc detected *** malloc(): memory corruption (fast): 0x097d7fa8 ***
-
Der vector-Ctor sollte eigentlich keine Probleme haben. Aber womöglich hast du den Heap schon vor diesem Aufruf zerlegt. Wie sieht denn der Ctor der Klasse Matrix<> aus?
(btw, den Parameter 'index' kannst du auch weglassen -der Default-Ctor legt bereits einen vector mit 0 Elementen an)
PS: Da fehlt übrigens ein '#include <vector>' - und statt der C-Header solltest du ihr C++ Äquivalent (<cxxx> anstelle von <xxx.h>) verwenden.
-
Ersteinmal danke fuer die schnelle Antwort - ich weiss aber leider nicht was ein Ctor ist - sorry
-
Ctor steht für Constructor und Dtor für Destructor,
Gruß Paddy
-
Ok ich bin nicht 100%ig sicher, aber ich wuerde sagen die ersten 2 Zeilen sind der Ctor - zur sicherheit habe ich mal den kompletten public-Bereich kopiert
Matrix(); Matrix( int rows, int cols ); // size rows x cols Matrix ( const Matrix & mat); // copy constructor ~Matrix(); // Assignment const Matrix& operator = (const Matrix & Rmat); // Accessors int numrows( ) const; // number of rows int numcols( ) const; // number of columns const vector<ItemType>& operator[] (int index) const; // Modifiers vector<ItemType>& operator[] (int index); void resize( int newRows, int newCols ); // resizes matrix to // newRows x newColsSieht aber wirklich fast so aus, dass ich davor irgendwas falsch gemacht habe - weil wenn ich die Deklaration einfach an den Anfang des Programms setze hat er keine Probleme mehr damit. Naja ich mache jetzt einfach mal so weiter und hoffe dass es so klappt

Vielen Dank ihr zwei
-
Ja, die ersten drei Zeilen sind die Construktoren deiner Matrix-Klasse. Aber für die Fehlersuche dürfte es hilfreicher sein zu wissen, was sie eigentlich machen (in deinem Programm besonders der zweite -"Matrix(int rows,int cols);").
PS: Sorry für die Verwirrung - das ist die Macht der Gewohnheit

-
Die ersten drei Zeilen sind definitionen von Konstruktoren (Ctor's) und die vierte zeile ist der dtor