2013-10-16 21 views
5

char ürününü Token s dosyasına dönüştürmek için basit bir C programı yazdım. İşler iyi çalışıyor ama neden size değişken değerinin değiştiğini anlayamıyorum. code"abcde" içerenC değişkeni için ifade edilemeyen bir değişiklik var

typedef struct _token { 
    int val; 
} Token; 

void parse(char* code, int size, Token** tokens) { 
    int i = 0; 
    for (; i < size; i++) { 
     tokens[i] = malloc(sizeof(Token)); 
     tokens[i]->val = code[i]; 
    } 
} 

int execute(char *path) { 
    char* code; 
    if (read_file(path, &code) != 0) { 
     return -1; 
    } 
    int size = strlen(code) - 1; 
    printf("BEFORE PARSE: %d\n", size); // 1st printf 
    Token *tokens; 
    parse(code, size, &tokens);   
    printf("AFTER PARSE: %d\n", size);  // 2nd printf 
    return 0; 
} 

eğer çıkışı: Farklı pistlerinde

BEFORE PARSE: 5 
AFTER PARSE: 142786584 

ikinci printf görüntüler farklı değerler.

Lütfen yardım edin!

PS: Ben bir C noob'um!

DÜZENLEME:

int read_file(char* path, char** code) { 
    FILE* fp = fopen (path , "rb"); 
    if(!fp) { 
     return -1; 
    } 

    fseek(fp , 0L , SEEK_END); 
    long lSize = ftell(fp); 
    rewind(fp); 

    /* allocate memory for entire content */ 
    *code = calloc(1, lSize+1); 
    if(!*code) { 
     fclose(fp); 
     return -1; 
    } 

    /* copy the file into the buffer */ 
    if(1 != fread(*code , lSize, 1 , fp)) { 
     fclose(fp); 
     return -1; 
    } 

    fclose(fp); 
    return 0; 
} 
+2

Sen malloc simge gerekir. –

cevap

3

Sen tampon taşma tipik durum var.

char* code; 

Dosya verilerinizi tutmak için arabelleğe değil, işaretçiyi (genellikle 8 bayt) atar.

Eğer parse yılında tokens yazma ne zaman yığınının parçası üzerine

Token *tokens; 

ile aynı

ve onunla size.

Onlar için yeterli bellek ayırın! İşte

read_file(path, code); 
parse(code, size, tokens); 

kodu düzeltilir:

char * code = malloc(0x1000); 
Token *tokens = malloc(0x100 * sizeof(Token *)); 

Ve işaretçi geçmek değil adresim Eğer ayrıştırma aramadan önce

typedef struct _token { 
    int val; 
} Token; 

void parse(char* code, int size, Token* tokens) { 
    int i = 0; 
    for (; i < size; i++) { 
      // you already have memory now 
     tokens[i]->val = code[i]; 
    } 
} 

int execute(char *path) { 
    char* code = malloc(0x1000); 
    if (read_file(path, code) != 0) { 
     return -1; 
    } 
    int size = strlen(code) - 1; 
    printf("BEFORE PARSE: %d\n", size); // 1st printf 
    Token *tokens = calloc(sizeof(Token), 0x100); 
    parse(code, size, tokens);   
    printf("AFTER PARSE: %d\n", size);  // 2nd printf 
    return 0; 
} 
+0

Sen Tokens hakkında haklısın, ama kodun muhtemelen read_file() 'de ayrılmış bir arabelleğe işaret etmek için değiştirildiğini görüyorum. Bu, execute() –

+0

@ChrisStratton May be içinde kullanılan uygulama stiliyle tutarlı olacaktı. Read_file için kod sağlamıyordu, bu yüzden emin olamıyorum. Yine de oldukça sıradışı olurdu. –

+0

& Operatörün kullanımı için mantıksal açıklama ve sağlanan kod ile stilistik olarak tutarlı. Ayrıca, bir şekilde haklı olsanız bile, bu sorun, yalnızca daha sonra ortaya çıkan problemin sebebi olamazdı. –

5

belirteçleri hiçbir zaman başlatıldı çünkü öyle.

Tokens **tokens = malloc(sizeof(Tokens *) * size); 
onunla bittiğinde

belleği boşaltmak unutmayın : Değiştirmek o

for (; i < size; i++) { 
    free(tokens[i]); 
} 

free(tokens); 
+0

Ücretsiz (token [i]) 'yi aramak istediğinizden emin misiniz? İşaretçi yerine bir yapı geçiyorsunuz. Ayrıca, sadece bir kez 'malloc()' olduğunu ancak bir döngü içinde 'free()' dediğiniz konusunda uyarılmış olabilirsiniz. Bu şekilde asla eşleşemezler. –

+0

Ayrıca, "Token" değil, "Token" türünde olan bir dizi tahsis edilirken, "sizeof (Tokens *)" yanlıştır. –

+1

@ PavelŠimerda içinde parse() 'o bireysel Token yapıları tahsis ediyor:' tokenler [i] = malloc (sizeof (Token)); 'so-tokens' bir Token * dizisidir. Ama evet, doğru olması için, “jetonlar”, “Token **” olarak ilan edilmeli ve ayrıştırmanın ona nasıl eriştiğini de güncellemelidir. –