[c++] Segmentation Fault

Hallo!
Ich habe das Problem, dass ich immer ein Segmentation Fault bekomme und nicht weis, warum. Ich bin mir schon im Klaren, was das bedeutet. Nur den Grund versteh ich nicht.
Das ganze sieht etwa so aus:
Code:
char** stringArray = new char*[100]; //Diehier ist global und wird in 
//einer anderen Funktion mit Inhalt versehen

void Beispielfunktion(const char *text)
{
	int x=0;
	while (stringArray[x]!="") //Vlt. würde es auch ne For Schleife tun... ^^ aber ich mag while
	{
		if (str_find_nocase(text,stringArray[x])) //Hier liegt der Fehler
			*Mach Irgendwas*;
		x++;
	}
}
(kompiliere mit gcc)
Das Problem ist nur, dass ich mich nicht so besonders mit char arrays auskenne. Arrays von char arrays sind ne richtige Herausforderung. Strings kann ich hier leider nicht verwenden (Projektbedingt). :/

Danke svhonmal in Voraus!
 
du reservierst nur speicher für pointer auf strings und keinen speicher für die strings. dazu kommt noch, dass die pointer ins nirvana zeigen. das ist aber soweit alles ok, solange du in der anderen funktion von der du sprichst den speicher für die strings allocierst und die pointer entsprechend setzt. Ich hoffe mal das ist so gewollt.

Die Schleifenbedingung ist nicht sonderlich toll, es sei denn du kannst 100%ig sicherstellen, dass das array immer nen pointer auf nen nullbyte enthält.

Mit dem eigentlichen Problem wird dir leider keiner weiterhelfen können, wir können ja den code von str_find_nocase nicht erraten.

Zumindest der code den du gepostet hast, segfaultet nicht.
 
solange du in der anderen funktion von der du sprichst den speicher für die strings allocierst und die pointer entsprechend setzt.
Nein, das hab ich wohl nicht gemacht.
Nur für jeden String stringArray[x]=y; (wobei x ein int ist und y ein char *).
Wie müsste das denn aussehen? Diesem Tutorial bin ich nachgegangen.

Die str_find_nocase(..) Funktion vergleicht nur 2 char arrays. Die läuft aber garantiert fehlerfrei.
 
Original von Extinction
while (stringArray[x]!="") //Vlt. würde es auch ne For Schleife tun... ^^ aber ich mag while

was genau soll diese Zeile machen?
stringArray ist ein Pointer auf ein Array voller char-Pointer. Du gehst dann dieses Array durch und in der Abbruchbedingung vergleichst du, ob der char-Pointer die gleiche Adresse hat wie der vom Compiler temporär angelegte String "" (leerer String). Wenn du irgendwo im code "abcdef egal was hier steht" schreibst, speichert der Compiler diesen temporären String _an einer beliebigen Adresse_ im Speicher ab. Ob dein char* im stringArray da draufzeigt ist reine Glückssache.
Was du wohl machen wolltest, ist, zu schauen, ob der stringArray[x] ein leerer String ist, oder?
da so, wie du es gemacht hast, nur die Adressen der (c-)strings verglichen werden (und es kann ja auch an mehreren Stellen im Arbeitsspeicher die gleiche Zeichenkette stehen, deine Methode würde trotzdem sagen, dass das zwei unterschiedliche Strings sind (da die Zeichenketten eben an unterschiedlichen Adressen im Speicher stehen)).
Um den Inhalt (nicht die Adressen) zweier Strings zu vergleichen, musst du strcmp(char*, char*); benutzen, diese funktion geht die Strings Zeichen für Zeichen durch und macht so viel eher das, was du willst.
Falls du also wirklich überprüfen wolltest, ob das ein leerer String ist, solltest du
Code:
while(strcmp(stringArray[x], "")) {...}
benutzen.

Die segfault kam übrigens daher, dass die Schleife immer weiter gelaufen ist (weil es ja nicht an der Stelle abgebrochen hat, an der es sollte) und irgendwann den nicht deinem Programm zugeteilten Speicher erreicht hat und dann schließlich versucht hat, diesen zu überschreiben. Dies verbietet das Betriebssystem natürlich und lässt das Programm dann als Strafe kläglich sterben.
 
Original von Heinzelotto
Wenn du irgendwo im code "abcdef egal was hier steht" schreibst, speichert der Compiler diesen temporären String _an einer beliebigen Adresse_ im Speicher ab. Ob dein char* im stringArray da draufzeigt ist reine Glückssache.
Was du wohl machen wolltest, ist, zu schauen, ob der stringArray[x] ein leerer String ist, oder?
da so, wie du es gemacht hast, nur die Adressen der (c-)strings verglichen werden (und es kann ja auch an mehreren Stellen im Arbeitsspeicher die gleiche Zeichenkette stehen, deine Methode würde trotzdem sagen, dass das zwei unterschiedliche Strings sind (da die Zeichenketten eben an unterschiedlichen Adressen im Speicher stehen)).
Um den Inhalt (nicht die Adressen) zweier Strings zu vergleichen, musst du strcmp(char*, char*); benutzen, diese funktion geht die Strings Zeichen für Zeichen durch und macht so viel eher das, was du willst.
Falls du also wirklich überprüfen wolltest, ob das ein leerer String ist, solltest du
Code:
while(strcmp(stringArray[x], "")) {...}
benutzen.

ich dachte zunächst auch, dass string != "" schwachsinn wäre, hab dann aber vor meinem post mal folgenden test gemacht:
Code:
char* a = "abc";
if(a == "abc")
{
// Fall a
}
else
{
//Fall b
}

und bin dabei iin Fall a gelandet. Eiine erklärung wäre, dass der compiler die ckonstante immer an der gleichen adresse hat, eine andere, dass er wirklich strings vergleicht, hab mir das assmbly dazu nicht angesehen.

Nun nochmal zu Extinctions Frage:
Du musst wissen, dass c-strings arrays von char sind. ein char* zeigt also auf einen solchen string. wenn du new char*[100] machst, reservierst du ausschleißlich speicher für die pointer auf die strings. die zuweisung char* a = "abc" bewirkt, dass der compiler den speicher für den eigentlichen string für dich erledigt und a dann auf diesen speicher zeigt. wenn du das irgendwie anders machst (ohne die zuweisung einer konstante) musst du nen char* a = new char[STRINGLAENFE+1] machen und dann was in den reservierten speicher schreiben. Wenn du es detailierter brauchst müsstetst du mal genauer posten, was du machen möchtest.
 
Original von ArnoNühm
und bin dabei iin Fall a gelandet. Eiine erklärung wäre, dass der compiler die ckonstante immer an der gleichen adresse hat, eine andere, dass er wirklich strings vergleicht, hab mir das assmbly dazu nicht angesehen.

die erklärung dafür ist, dass der compiler weiß, dass das zweimal das gleiche ist, und da das implizit ein const char* ist und somit niemals verändert werden kann, gibt es für den compiler keinen grund, dafür zweimal Speicher zu verwenden. Deshalb wird es so optimiert, dass es zweimal die selbe Speicheradresse ist.
 
Wenn du es detailierter brauchst müsstetst du mal genauer posten, was du machen möchtest.
Also, was ich im Grunde genommen machen möchte, ist folgendes, nur mit char* statt mit std::string
(mal schnell getippt, nicht getestet)
Code:
#include <string.h>
using namespace std;
string stringArray[100];
//ich dachte, die char* Variante sei char** stringArray = new char*[100];

void fill_array(string test) //dashier soll ein char * werden, funktioniert soweite auch
{
    for (int i=0; i<99;i++)
    {
        stringArray[i]=test //wen ich bei der char* Variante strcpy benutze, kommt hier wieder ein Seg. Fault
        //Bei der char* Variante habe ich hier auch noch eine Nullterminierung hinzugefügt: stringArray[i]= test + '\0'
        cout << stringArray[i] << endl; //Mit char* kommt hier noch eine korrekte Ausgabe
    }
    stringArray[99]="";
}

void greif_drauf_zu()
{
    int x=0;
    while(stringArray[x]!="") //Daher rührte mein erster Fehler... In Strings gedacht.
    {
        cout << "String lautet:" <<  stringArray[x] << endl; //Hier werden bei der char* Variante nur willkürliche Zeichen ausgegeben
        x++;
    }
}
Ja, mit Strings währe es einfacher, aber es muss leider mit char* gehen.
Ich hoffe, das drückt es genau genug aus. :)
 
in fill array machst du:
Code:
stringArray[i]=test
setzt mal davor noch:
Code:
stringArray[i] = new char[strlen(test) + 1];

Damit reservierst du speicher für deinen string und lässt stringArray drauf zeigen. dann funktioniert auch stringcopy. Wenn du das dann so machst kannst du, nachdem du dein Array verarbeitet hast mit "delete[] array;" den speiche für die einzelnen strings wieder freigeben, sonst baust du nen speicherleck.

Damit erledigt sich das andere Problem dann wohl auch.

Wenn du die länge deines Array kennst, solltest du die auch als abbruchbedingung verwenden, das vermeidet Fehler.
 
Achso...
Scheinbar habe ich bei der Initialisierung nur Speicher für den pointer Array reserviert, nicht aber für die Strings selbst. Das ganze funktioniert jetzt.
1000-Dank :)
 
Zurück
Oben