realloc( )-Problem?
-
Hi!
Ich habe ein Problem mit realloc( ) und/oder Zeigern, das komplett meine geistige Kapazitaet uebersteigt.Zuerst mein Code:
#ifndef SPLIT__ #define SPLIT__ struct split { char **data; int nstr, rc; }; #define SPLIT_EATREP 1 struct split split( char *input, char *tokens, int options ); #endif #include <stdio.h> #include <string.h> #include <stdlib.h> static int do_copy( char ***data, char *buf, int *alloc, int *index ) { const int basesize = 10; int alloctmp = *alloc, indextmp = *index; char **datatmp = *data, **tmp; if( indextmp >= alloctmp ) { alloctmp += basesize; tmp = realloc( datatmp, alloctmp * sizeof( char* ) ); if( tmp == NULL ) { int i; for( i = 0; i < indextmp; ++i ) { free( datatmp[i] ); } free( datatmp ); return 1; } *alloc = alloctmp; datatmp = tmp; } datatmp[indextmp] = strdup( buf ); printf( "%d: %s\n", indextmp, datatmp[indextmp] ); ++*index; return 0; } struct split split( char *input, char *tokens, int options ) { struct split result; char buf[1024], *p, *tmp, **str, **tmp2; const int basesize = 10; int i, alloc = 0, index = 0, inmodfl = 0; str = malloc( basesize * sizeof( char* ) ); if( str == NULL ) { result.rc = 1; return result; } while( *input ) { for( i = 0; i < 1024 && *input; ++i, ++input ) { for( tmp = tokens; *tmp; ++tmp ) { if( *input != *tmp ) { continue; } if( i == 0 ) { /* avoid copying nul-string */ tmp = tokens - 1; ++input; continue; } buf[i] = 0; if( do_copy( &str, buf, &alloc, &index ) != 0 ) { result.rc = 1; return result; } printf( "%d: %p\n", index - 1, str[index - 1] ); ++input; i = 0; inmodfl = 1; if( options & SPLIT_EATREP ) { tmp = tokens - 1; /* undefined behaviour :( */ continue; } break; } buf[i] = *input; } } if( i > 0 ) { buf[i] = 0; if( do_copy( &str, buf, &alloc, &index ) != 0 ) { result.rc = 1; return result; } } if( index >= alloc ) { tmp2 = realloc( str, ( alloc + 1 ) * sizeof( char* ) ); if( tmp2 == NULL ) { for( i = 0; i < index; ++i ) { free( str[i] ); } free( str ); result.rc = 1; return result; } str = tmp2; } str[index] = NULL; result.data = str; result.nstr = index; result.rc = 0; return result; } void split_clean( struct split *s ) { int i; if( s->rc == 0 && s->data != NULL ) { for( i = 0; i < s->nstr; ++i ) { free( s->data[i] ); } free( s->data ); s->data = NULL; s->rc = 1; } } int main( ) { char buf[128]; struct split s; s = split( "hello hello hello hello hello hello hello hello hello hello hello hello hello hello" , " ", 0 ); if( s.rc == 0 ) { int i; for( i = 0; i < s.nstr; ++i ) { printf( "%d: %p\n", i, s.data[i] ); } split_clean( &s ); } else { perror( "split" ); } getchar( ); return 0; }
split( ) soll einen String nach den festgelegten Zeichen trennen, Kopien davon machen und zurueckgeben. Prinzipiell funktioniert das ganz gut, aber die jeweils elfte Kopie eines Teilstueckes enthaelt immer Schrott, d.h. bei gcc 3.2 NULL, bei MinGW irgendwelche Schrott-Adressen. Das erstaunliche ist, dass die printf-Ausgabe in do_copy( ) bei der elften Kopie IMMER korrekt ist, die direkt danach aber nicht. Man kann uebrigens ``basesize'' aendern und erhaelt dann genauso Schrott an der entsprechenden Stelle, also z.B. bei basesize = 5 wird der sechste String im Eimer sein.
Mehr kann ich zu dem Problem nicht sagen, da ich voellig hilflos bin und keine Ahnung habe, was los ist. Koennte bitte jemand den Code mit einem anderen Compiler/einer anderen Standard-C-Library testen, oder mir sagen, wo der Fehler liegt?
Danke im Voraus.
-
Haha, ich bin so eine Sacknase
*data = datatmp; vor return 0 und es funktioniert.