![]() |
Anzeige:
|
|
|||||||
| C/C++, Visual C++, Visual C++.NET Fragen und Antworten zu C/C++, Visual C++ und Visual C++.NET |
|
![]() |
|
|
LinkBack | Themen-Optionen | Ansicht |
|
|
#1 (Direktlink) |
|
Weiß worum´s geht
![]() Registriert seit: 31.03.2009
Ort: localhost
Beiträge: 222
|
Guten Abend allerseits
Ich wollte mir mal ein paar nützliche Funktionen in C schreiben, die funktionieren auch super. Allerdings hab ich die jetzt mal testweise kombiniert und jetzt fängt es an zu hacken. Die Datei um die es geht, ist angehängt. Ich nutze gcc (Debian 4.3.3-3) 4.3.3 Beim compilen funktioniert alles wunderbar, allerdings beim starten kommen Fehler. Wenn ich in die char **explode funktion in die while schleife ein i<[1-8] packe, kommt am Ende nur ein Speicherzugriffsfehler, andernfalls (so wie die Datei ist) kommt noch realloc(): invalid next size.... Ich komme echt nicht darauf, wo der Fehler liegen sollte, da die Ausgabe diese hier ist: Code:
x: # x: #i x: #in x: #inc x: #incl x: #inclu x: #includ x: #include x: #include x: #include < x: #include <s x: #include <st *** glibc detected *** ./a.out: realloc(): invalid next size Vll kann mir hier jemand helfen Ansonsten wüsste ich noch gerne, ob die Funktionen sicher sind (BOFs) und ob sie Speicherlecks enthalten. Danke schonmal Geändert von Schwert (11.02.2010 um 15:56 Uhr) |
|
|
|
|
|
|
#2 (Direktlink) |
|
War schon mal da
![]() Registriert seit: 06.02.2010
Beiträge: 27
|
Sorry, aber ich steig durch deinen Code nicht durch. Ein paar Fragen:
1) Warum alloziierst du alle möglichen lokalen Variablen auf dem Heap? Das bringt keinerlei Vorteil und verwirrt nur. 2) Was ist der Sinn dieser Zeile: "tmp = malloc(0*sizeof(char));" 3) Wieso wird im folgenden Code 2mal überprüft ob size==NULL? Code:
if(size == NULL) {
return NULL;
}
if(NULL == size) {
free(tmp);
free(arr);
return explode(str, delimiter, lim, size);
}
|
|
|
|
|
|
#3 (Direktlink) |
|
Weiß worum´s geht
![]() Registriert seit: 31.03.2009
Ort: localhost
Beiträge: 222
|
cx01: Danke für deine Antwort.
zu 1: Manche der Funktionen hab ich geschrieben, wie ich angefangen habe C zu lernen. Damals dachte ich, man benutzt malloc/calloc/realloc, weil wenn man einfach nur "int i=bla" benutzt, ein Speicherleck hat, wenn das öfter aufgerufen wird (in einer Schleife ist), weil ich dachte, dass der Speicher nicht wieder freigegeben wird. Das war dort wo ich es gelernt habe ziemlich missverständlich erklärt, mittlerweile weiß ich es besser. Außerdem finde ich es in manchen Fällen einfacher/schöner mit Zeigern/eigenem reserviertem Speicher zu arbeiten zu 2: Der Sinn davon ist, dass, bevor ich realloc anwende, malloc oder calloc anwenden muss. realloc wird später in der Schleife benutzt. Mann kann auch 1*sizeof(char) machen, allerdings ist dann immer die Größe eines chars zuviel und ich dachte mir, ich lass es lieber genausogroß wieder Inhalt zu 3: Das mit dem Size stimmt, das war mein Fehler und zwar hab ich das erst gemacht, wie bei jeder Alloziierung um zu testen, ob es geklappt hat, bis mir aufgefallen, dass size ein Parameter ist um die größe das Arrays zurückzugeben. Bzw hab ich dies im nachhinein geändert. Ich werde 2. rausnehmen, danke zu 4: In gewisserweiße ja, die Aufgabe des aktuellen Projektes ist zwar nicht lebensnotwendig für das System, allerdings ist es ein wichtiger Bestandteil der Sicherheit des Systems und ich will auch sicher programmieren. Da ich die Funktionen in verschiedenen Projekten verwenden werde, will ich sie halt einmal richtig programmieren. Ich hab die Datei jetzt noch klein wenig verändert und hab sie nochmals angehängt Geändert von Schwert (11.02.2010 um 15:56 Uhr) |
|
|
|
|
|
#4 (Direktlink) |
|
War schon mal da
![]() Registriert seit: 06.02.2010
Beiträge: 27
|
Und was ist der Sinn der Explode Funktion? Sie zerteilt einen String in mehrere Teilstrings? Was bewirken die Parameter lim und size?
|
|
|
|
|
|
#5 (Direktlink) |
|
Weiß worum´s geht
![]() Registriert seit: 31.03.2009
Ort: localhost
Beiträge: 222
|
size ist ein Zeiger für die größe des Arrays. Der Speicher wird vor dem aufruf der Funktion vom Programmierer reserviert und somit kann ich quasi mehrere Werte "returnen", da ja die Speicheraddresse gespeichert ist und ich nur den Wert ändere.
lim ist das Limit, wie groß das Array maximal werden darf. Edit: Ja, das ist der Sinn der explode Funktion |
|
|
|
|
|
|
#6 (Direktlink) |
|
War schon mal da
![]() Registriert seit: 06.02.2010
Beiträge: 27
|
Ich bin leider durch deinen Code nicht durchgestiegen und hab mal eine eigene Variante programmiert. Gut möglich, dass da noch Bugs drinstecken. Bin leicht übermüdet
Code:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char **explode(char *str, char *delimiter, int *arr_size)
{
int str_len = strlen(str);
int delimiter_len = strlen(delimiter);
int i = 0;
int start_of_match = 0;
int end_of_match = 0;
int matched = 0;
*arr_size = 0;
char **arr = malloc(*arr_size*sizeof(char*));
while(1)
{
end_of_match = i;
matched = 0;
while(str[i+matched] == delimiter[matched])
{
matched++;
if(matched==delimiter_len || i+matched>=str_len)
{
//wir haben ein match
i += matched;
int match_len = end_of_match - start_of_match;
if(match_len == 0)
{
start_of_match = i;
break;
}
char* res = malloc((1 + match_len) * sizeof(char));
memcpy(res, str + start_of_match, match_len);
res[match_len] = 0;
//array vergroessern
*arr_size += 1;
arr = realloc(arr, *arr_size*sizeof(char*));
//match ins array einfügen
arr[*arr_size-1] = res;
start_of_match = i;
if(i>=str_len) return arr;
break;
}
}
i++;
}
}
int main()
{
char* m = "tABC1953ABC59209ABCD34ABC";
char* d = "ABC";
int elems = 0;
char **arr = explode(m, d, &elems);
int i=0;
for(;i<elems;i++)
{
printf("%s\n", arr[i]);
}
}
|
|
|
|
|
|
#7 (Direktlink) |
|
Weiß worum´s geht
![]() Registriert seit: 31.03.2009
Ort: localhost
Beiträge: 222
|
Ok, danke!
Deine Variante ist schonmal viel übersichtlicher als meine xD Werde mir da wohl dann auch n Beispiel dran nehmen. Bei so einem normalen String funktioniert meine explode Funktion auch Ich hab jetzt einfach mal deine explode Funktion in meinen Code eingefügt und dann den Funktionsaufruf noch angepasst. Wenn ich jetzt *file_get_contents("mysql_check.c"); als *str nehme, dann bekomm ich zwar diesmal das ganze Ergebnis, ohne realloc Fehler, allerdings steht unterdem ganzen wieder Speicherzugriffsfehler. Ich hänge die Datei nochmals an Du musst die Datei nur in mysql_check.c umbennenen, da ist hier keine *.c Dateien hochladen kann. Wo steigst du den bei meinem Code noch nicht durch? Dann kann ich es dir vll erklären oder das was du nicht verstehst ist genau mein Fehler Edit: Ich sehe gerade, die letzte Zeile der Datei wird bei deiner Funktion dann nicht ausgegeben Geändert von Schwert (11.02.2010 um 15:56 Uhr) |
|
|
|
|
|
#8 (Direktlink) |
|
War schon mal da
![]() Registriert seit: 06.02.2010
Beiträge: 27
|
Die file_get_contents Methode scheint fehlerhaft zu sein, zumindest krieg ich eine Exception an folgender Stelle (in der Zeile mit strncat):
Code:
if(datei != NULL) {
while( (*zeichen = getc(datei)) != EOF) {
strncat(str, zeichen, 2);
}
}
Was ich an deinem Code nicht verstehe? Nunja, ist natürlich immer leichter den eigenen Code zu lesen, und irgendwie glaub ich, dass dein Code komplizierter ist als er sein müsste. EDIT: Ich seh grad, die file_get_contents Funktion ist extrem ineffizient. Normalerweise benutzt man fread() oder fgets() für solche Situationen. Geändert von cx01 (07.02.2010 um 13:39 Uhr) |
|
|
|
|
|
#9 (Direktlink) |
|
Weiß worum´s geht
![]() Registriert seit: 31.03.2009
Ort: localhost
Beiträge: 222
|
file_get_contents hab ich mehrfach getestet und genutzt. Bei mir funktioniert die Funktion fehlerfrei, auch wenn ich die Variable ausgebe.
Nein, ich nutze keinen Debugger, ich lass mir nur verschiedene Variablen beim programmieren ausgeben oder schreib sie manchmal auch in Dateien. Du hast Recht, mein Code ist/war viel zu umständlich, bin mittlerweile hier Code:
char **explode(char *str, char *delimiter, int lim, int *size) {
if(size == NULL) {
return NULL;
}
*size = 1;
char **arr;
arr = (char **)malloc(*size*sizeof(char **));
if(NULL == arr) {
return explode(str, delimiter, lim, size);
}
int limit;
if(lim < 0) {
limit = 1;
} else {
limit = lim;
}
char *test;
char *tmpt;
int i = 0;
int delimiter_len = strlen(delimiter);
int str_len = strlen(str);
int z = 0;
while(*size < limit && i < str_len) {
test = substr(str, i, delimiter_len);
if(strncmp(test, delimiter, delimiter_len) == 0) {
if(lim < 0) {
limit++;
}
(*size)++;
z++;
arr = (char **)realloc(arr, (*size)*sizeof(char *)); //nulltest
i += delimiter_len;
} else {
tmpt = substr(str, i, 1);
if(NULL == arr[z]) {
arr[z] = tmpt;
} else {
arr[z] = (char *)realloc(arr+(z), sizeof(arr[z])+sizeof(tmpt)); //nulltest
strncat(arr[z], tmpt, strlen(tmpt));
free(tmpt);
}
i++;
}
free(test);
}
return arr;
}
ich werde mir file_get_contents dann noch mal anschauen Edit: Die Fehler liegen bei arr[z] = (char *)realloc(arr+(z), sizeof(arr[z])+sizeof(tmpt)); und strncat(arr[z], tmpt, strlen(tmpt)); Allerdings bekomm ich die Fehler nicht weg |
|
|
|
|
|
#10 (Direktlink) |
|
War schon mal da
![]() Registriert seit: 06.02.2010
Beiträge: 27
|
Ich kriege eine Exception im malloc() Aufruf in der Funktion substr. Das kann eig nicht sein, daher vermute ich, dass du irgendwo ausversehen Speicherbereiche überschreibst, in die du nicht schreiben solltest. Weiss jedoch noch nicht wo...
EDIT: Die von dir gepostete Stelle könnte der Fehler sein. Ich glaube sizeof(arr[z]) gibt nicht die Länge des Array, sondern nur die sizeof(char*) zurück. |
|
|
|
|
|
|
#11 (Direktlink) |
|
Weiß worum´s geht
![]() Registriert seit: 31.03.2009
Ort: localhost
Beiträge: 222
|
Ich hab die Funktion file_get_contents jetzt mal umgeschrieben:
Code:
char *file_get_contents(char *filename) {
if(file_exists(filename) == 0) {
return NULL;
}
FILE *datei;
char *str = NULL;
fpos_t *size = NULL;
datei=fopen(filename, "r");
if(NULL == datei) {
return file_get_contents(filename);
}
size = (fpos_t *)malloc(sizeof(fpos_t));
if(NULL == size) {
free(datei);
return file_get_contents(filename);
}
fgetpos(datei, size);
str = (char *) malloc((size_t)size);
if(NULL == str) {
free(datei);
return file_get_contents(filename);
}
fread(str, sizeof(char), (size_t)size, datei);
free(size);
free(datei);
return str;
}
das mit der Exception wundert mich jetzt auch etwas. Es kann nicht daran liegen, dass ich: tmpt = substr(str, i, 1); if(NULL == arr[z]) { arr[z] = tmpt; } und arr[z] danach mit realloc erweitere? und du hattest Recht: sizeof(arr[z]) gibt nur sizeof(char) zurück Ich hatte vorhin testweise sizeof(arr[z]) ausgegeben und mich gewundert, warum es 1000 mal hintereinander nur 4 ist, obwohl es ja durch realloc lief. Die Zeile sieht jetzt so aus: arr[z] = (char *)realloc(arr+(z), strlen(arr[z])+sizeof(tmpt)); hab die Datei jetzt noch mal hochgeladen. Wenn ich in Zeile 173 printf("%s\n", arr[z]); einkommentiere, sehe ich, dass die Datei anscheinend mehrmals durchlaufen wird, was mir gerade komisch vorkommt und ich bin deshalb leicht verwirrt Ok: hab das jetzt so aufgerufen: gcc mysql_check.c && ./a.out | grep *file_get und es kommt so oft, dass ich in der shell oben nichts anderes mehr sehe. Was nutzt du den für einen Debugger? Geändert von Schwert (11.02.2010 um 15:56 Uhr) |
|
|
|
|
|
#12 (Direktlink) |
|
War schon mal da
![]() Registriert seit: 06.02.2010
Beiträge: 27
|
Zur file_get_contents Methode: Sieht auf den ersten Blick gut aus. Ich würde alle lokalen Variablen auf dem Stack alloziieren; das ist leichter zu lesen und performanter.
Als Debugger benutze ich Visual C++ 2008 Express; falls du Windows User bist, kannst du dir das kostenlos downloaden. Woran die Exception liegt, weiss ich immernoch nicht |
|
|
|
|
|
#13 (Direktlink) |
|
Weiß worum´s geht
![]() Registriert seit: 31.03.2009
Ort: localhost
Beiträge: 222
|
Ok, also ich probiere es jetzt seit heut und gestern mit einem Debugger zufinden.
Ich hab das Gefühl, dass in der file_get_contents Funktion ein Fehler vorliegt. Wenn mann str=file_get_contents("path/to/file.endung"); free(str); macht, kommt kein Fehler, gebe ich jetzt allerdings noch printf("%s\n", str); dazwischen ein, kommt: Code:
Conditional jump or move depends on uninitialised value(s)
at 0x4025BC7: strlen (mc_replace_strmem.c:275)
by 0x4092D94: puts (ioputs.c:36)
by 0x8048E7D: main (in a.out)
Das Ergebnis von strlen ist aber 383, was genau dem Inhalt der Datei entspricht, auch printf() gibt den Inhalt richtig aus. Edit: Ich hänge die Datei nochmal an Geändert von Schwert (11.02.2010 um 15:56 Uhr) |
|
|
|
|
|
#14 (Direktlink) |
|
War schon mal da
![]() Registriert seit: 06.02.2010
Beiträge: 27
|
Hier ist ein Beispiel, wie man eine Datei einliest: fread - C++ Reference
Kannst du eig direkt übernehmen. |
|
|
|
|
|
#15 (Direktlink) |
|
Weiß worum´s geht
![]() Registriert seit: 31.03.2009
Ort: localhost
Beiträge: 222
|
danke!
Habs übernommen, bekomme allerdings immer noch den gleichen Fehler. Entweder sollte ich das Programmieren aufgeben oder mir nen Strick suchen, ich verzweifle hier echt Vllt sollte man diesen "Fehler" auch einfach nicht beachten? |
|
|
|
|
![]() |
|
| Lesezeichen |
| Themen-Optionen | |
| Ansicht | |
|
|
Ähnliche Themen
|
||||
| Thema | Autor | Forum | Antworten | Letzter Beitrag |
| Speicherzugriffsfehler | tobi.-.-.-. | C/C++, Visual C++, Visual C++.NET | 3 | 18.05.2005 14:33 |