2016-07-06 99 views
0

我正在研究一個腳本,它意味着在將文本轉換爲pdf文件之前將文本放在PostScript文件的末尾。分配的變量無法訪問

int main(int argc, char *argv[]){ 
    // Déclaration des variables 

    // Fichier source 
    char *source; 
    // Extension du fichier source 
    char *extension; 
    // Fichier de parametre 
    char *fichierPar; 
    // Numero et Type de folio du fichier 
    char *numeroFolio; 
    char *typeFolio; 

    // Tableaux contenant les types de folio a scanner 
    // suivant le numero de folio 
    char **t_F000 = NULL; 

    // Allocation des espaces mémoires nécessaires aux variables 
    source = malloc(sizeof(char) * strlen(argv[1])); 
    fichierPar = malloc(sizeof(char) * strlen(argv[2])); 
    extension = malloc(sizeof(char) * 5); 
    typeFolio = malloc(sizeof(char) * 4); 
    numeroFolio = malloc(sizeof(char) * 4); 

    // Grille de parametre 
    // AJUSTER LA TAILLE DU TABLEAU AVEC LE FICHIER DE LOGO.PAR 
    // DANS verification.h 
    Grille t_Grilles[NBGRILLE]; 

    // On copie les arguments dans des varibles plus explicites 
    strcpy(source, argv[1]); 
    strcpy(fichierPar, argv[2]); 

    // GetFolio appel getNumeroFolio qui appel getTypeFolio 
    // Ces deux fonctions extraient du nom de fichier 
    // le numero et le type de folio 
    getFolio(source, numeroFolio, typeFolio); 

    printf("strlen : %d\n", strlen(numeroFolio)); 
    fflush(stdout); 
    printf("numero : %s\n", numeroFolio); 
    fflush(stdout); 

    // Lecture du fichier LOGO.PAR et enregistrement en mémoire 
    chargerGrilles(fichierPar, t_Grilles); 

    printf("bonjour\n"); 
    fflush(stdout); 

    printf("strlen : %d\n", strlen(numeroFolio)); 
    fflush(stdout); 

    printf("numero : %s", numeroFolio); 
    fflush(stdout); 

工作並沒有停止在那裏,但我在這一點上阻止。
以下是ChargerGrille()的代碼;

void chargerGrilles(char *fichierPar, Grille t_Grilles[]){ 
    FILE *fdParam; 
    char *ligne; 
    Grille *grille; 
    int inc = 0; 

    grille = malloc(sizeof(Grille)); 

    ligne = malloc(sizeof(char) * 100); 

    fdParam = fopen(fichierPar, "rb"); 
    verifierOuverture(fdParam, fichierPar); 

    while(fgets(ligne, 100, fdParam)){ 
     if(verifierCommentaire(ligne) != 0){ 

      remplirGrille(grille, ligne); 
      t_Grilles[inc] = *grille; 

      inc++; 
     } 
    } 
    fclose(fdParam); 
} 

void remplirGrille(Grille *grille, char *ligne){ 
    char *split; 

    // Separation sur les espaces 
    split = malloc(strlen(ligne)); 
    split = strtok(ligne, " "); 
    strcpy(grille->nom, split); 
    split = NULL; 
    free(split); 

    split = malloc(strlen(ligne)); 
    split = strtok(NULL, " "); 
    grille->posX = strtof(split, NULL); 
    split = NULL; 
    free(split); 

    split = malloc(strlen(ligne)); 
    split = strtok(NULL, " "); 
    grille->posY = strtof(split, NULL); 
    split = NULL; 
    free(split); 

    split = malloc(strlen(ligne)); 
    split = strtok(NULL, " "); 
    grille->longX = strtof(split, NULL); 
    split = NULL; 
    free(split); 

    split = malloc(strlen(ligne)); 
    split = strtok(NULL, " "); 
    grille->hautY = strtof(split, NULL); 
    split = NULL; 
    free(split); 

    split = malloc(strlen(ligne)); 
    split = strtok(NULL, " "); 
    strcpy(grille->logo, split); 
    split = NULL; 
    free(split); 

    printf("Hello World !\n"); 
    fflush(stdout); 
} 

還有就是我的我的結構的聲明:

struct Grille{ 
    // Nom du tableau 
    char nom[4]; 

    // Position du point inferieur gauche 
    long int posX; 
    long int posY; 

    // Longueur X 
    long int longX; 
    // HAUTEUR Y 
    long int hautY; 

    // Nom du fichier logo.jpg 
    char logo[50]; 
}; 

typedef struct Grille Grille; 

在gdb中我可以打印 「源」, 「擴展」, 「fichierPar」,「numeroFolio」和 「typeFolio」 只是調用之前到chargerGrilles(fichierPar,t_Grilles);之後,這將無法訪問

108    chargerGrilles(fichierPar, t_Grilles); 
(gdb) print source 
$7 = 0x604010 "F290390001_SCH001-2.POS" 
(gdb) print numeroFolio 
$8 = 0x604090 "001" 
(gdb) n 
Hello World ! 
Hello World ! 
Hello World ! 
Hello World ! 
110    printf("bonjour\n"); 
(gdb) n 
bonjour 
111    fflush(stdout); 
(gdb) print source 
$9 = 0x303732 <error: Cannot access memory at address 0x303732> 
(gdb) print numeroFolio 
$10 = 0x53 <error: Cannot access memory at address 0x53> 

如果我把手錶上numeroFolio,GDB停止在這條線:

t_Grilles[inc] = *grille; 

分配的內存發生了什麼變化?爲什麼變量的地址會改變?


PS:不要照顧很多的printf/fflush的,這就是我試圖找出哪裏是段錯誤

+2

我建議你用英文而不是主語言編寫代碼,註釋和var/names/etc,以後再分享,維護和重用會更容易。對不起,但無關的評論。 – Tim

+1

't_Grilles [inc] = * grille;' - >'memcpy(&t_Grilles [inc],grille,sizeof(Grille));' – LPs

+1

你確定'inc LPs

回答

2

你面對的可能是通過訪問t_Grilles數組越界進入引起的問題chargerGrilles功能。訪問它與index > NBGRILLE調用Undefined Behavior,並在您的情況下,損壞其他主要局部作用域變量。

您必須確保環路while(fgets(ligne, 100, fdParam))負責t_Grilles大小。

因此,一個解決方案可以是:

while((fgets(ligne, 100, fdParam)) && (inc <NBGRILLE)) { 
    if(verifierCommentaire(ligne) != 0){ 

     remplirGrille(grille, ligne); 
     t_Grilles[inc] = *grille; 

     inc++; 
    } 
} 

最佳,從我的觀點來看,是添加一個參數函數來傳遞數組大小。

void chargerGrilles(char *fichierPar, Grille t_Grilles[], size_t size) 
{ 
    FILE *fdParam; 
    char *ligne; 
    Grille *grille; 
    size_t inc = 0; 

    grille = malloc(sizeof(Grille)); 

    ligne = malloc(sizeof(char) * 100); 

    if ((grille != NULL) && (ligne != NULL)) 
    { 
     fdParam = fopen(fichierPar, "rb"); 
     verifierOuverture(fdParam, fichierPar); 

     while((fgets(ligne, 100, fdParam)) && (inc < size)){ 
      if(verifierCommentaire(ligne) != 0){ 

      remplirGrille(grille, ligne); 
      memcpy(&t_Grilles[inc], grille, sizeof(Grille)); 

      inc++; 
      } 
     } 
    } 

    free(ligne); 
    free(grille); 
    fclose(fdParam); 
} 

chargerGrilles(fichierPar, t_Grilles, sizeof(t_Grilles)/sizeof(t_Grilles[0])); 

稱之爲正如你可以看到我的malloc ated變量還增加了檢查。你總是要檢查malloc返回值。否則,您可以調用Undefined Behavior

最後你必須freemalloc ated內存或你會看到內存泄漏。

+0

'memcpy'是不必要的。 OP正在執行直接結構分配,這在C中得到了支持。另一方面,「grille」和「ligne」的動態分配首先毫無意義;兩個都比簡單的當地人更合理。 – WhozCraig

+0

@WhozCraig我沒有強調'memcpy'的改變,因爲我是爲了清晰而做的。我同意,局部變量綽綽有餘。 – LPs