2015-01-01 41 views
0

我不是一個好英語的人。訪問限制內存時沒有分段錯誤

所以在我的程序中我想複製一個文本存在一個txt文件到一個數組。

typedef struct Chaine 
{ 
    char * Lachaine; 
    int Taille_C; 
} Chaine ; 

int main (void) 
{ 
    Chaine *Tab_Texte=NULL; 
    Tab_Texte=(Chaine*)malloc(sizeof(Chaine)); 
    FILE* Texte= NULL; 
    Texte = fopen("chaines", "r"); 
    fseek(Texte, 0, SEEK_END); 
    Tab_Texte->Taille_C=ftell(Texte); 
    fseek(Texte, 0, SEEK_SET); 
    Tab_Texte->Lachaine=NULL; 
    Tab_Texte->Lachaine=(char*)malloc(sizeof(char)*Tab_Texte->Taille_C); 
    fread(Tab_Texte->Lachaine,sizeof(char)*(Tab_Texte->Taille_C),1,Texte); 
    printf("%s",Tab_Texte->Lachaine); 

return 0; 
} 

這裏一切都很正常,當我改變

Tab_Texte->Lachaine=(char*)malloc(sizeof(char)*Tab_Texte->Taille_C); 

與(例如)

Tab_Texte->Lachaine=(char*)malloc(sizeof(char)*Tab_Texte->Taille_C - 10); 

它的工作原理始終,它想告訴我一個分割的錯,因爲sizeof(char)*Tab_Texte->Taille_C - 10較短比sizeof(char)*Tab_Texte->Taille_C等文件中的文字。

你能告訴我爲什麼它總是有效嗎?

+2

標題應該是「爲什麼我沒有得到分段錯誤?」。 – haccks

+0

要點1.不要強制轉換malloc()的返回值。要點2.如果這是'C++',則推薦使用'new'。第3點。您從未釋放分配的內存。將導致內存泄漏。 –

回答

3

它工作的原因總是因爲你描述的是undefined behavior所以它沒有真正定義應該發生什麼。

在某些情況下,它可能會導致segmentation fault,但並非總是如此。所以你的總是有時,但事實證明條件並不是segmentation fault發生的正確的條件。

考慮以下修正你的代碼:

  1. 你不應該這樣做

    printf("%s",Tab_Texte->Lachaine); 
    

    ,因爲你的Tab_Texte->Lachaine不是空值終止的

  2. 你可以嘗試做到像這

    fwrite(Tab_Texte->Lachaine, 1, Tab_Texte->Taille_C, stdout); 
    

    但通常你不會檢查每一個在代碼中失敗時返回null的函數。

    例如

    Texte = fopen("chaines", "r"); 
    if (Texte == NULL) 
        weAreInTroubleIfWeCall_fread_OnTexte_SoAbort(); 
    

    也適用於malloc,你不需要投malloc,讀this

  3. 你應該freemalloc的結果,當你不再需要它。

+1

好吧,你的觀點很正確,但答案是? –

+0

請將答案置於頂端,然後提出其他重要更改。 :-) –

+0

@SouravGhosh你的意見在哪裏非常有幫助,我把這個問題看成是'段錯誤!'而不是'沒有段...',但是我刪除了這些註釋,它們對OP沒有用。 –

1

你會得到一個segfault是你讀取或寫入到未分配給您的程序的內存。如果您濫用malloc,則可能無法獲得段錯誤,具體取決於底層操作系統將程序加載到內存中的方式。在這種情況下,您可能正在寫或讀自己的記憶,但在不同的地點,可能會覆蓋其他變量。

5

您遇到的情況稱爲undefined behavior

  • 訪問過去所分配的存儲器
  • 使用未空終止字符數組作爲字符串
  • 供給無效的文件指針

所有的[任何]這些將導致未定義的行爲和副作用可能是分段故障,但不能保證。

  1. 檢查的fopen()使用返回指針之前成功
  2. 空終止字符數組使用它作爲一個字符串
  3. free()分配的內存後的使用已經結束。
  4. 請勿施放返回值malloc()/calloc()
1

//沒有發生賽格故障事件的原因是因爲 //使用字段的內容代碼:Tab_Texte-> Taille_C //這是文件 的全尺寸// (所以除非文件沒有問題,具有小於10個字節)

//通過結構的適當定義,而這一個typedef消除代碼中的很多混亂的

//不從投malloc的返回值(和家庭)

//從malloc的檢查返回的值,以確保成功的操作

//檢查從的fopen返回值,以確保成功的操作

//檢查從FSEEK返回值,以確保成功的操作

//檢查從FTELL返回值,以確保成功的操作

//退出時程序,包括用於自由區域malloc分配,關閉文件等

//檢查retur清理nead value from fread以確保操作成功

#include <stdio.h> // fopen(), fclose(), fread(), fseek(), ftell() 
#include <stdlib.h> // exit(), EXIT_FAILURE, free(), malloc() 

struct Chaine 
{ 
    char * Lachaine; 
    int Taille_C; 
}; 

int main (void) 
{ 
    struct Chaine *Tab_Texte=NULL; 
    if(NULL == (Tab_Texte=malloc(sizeof(struct Chaine)))) 
    { // then, malloc failed 
     perror("malloc failed"); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, malloc successful 

    FILE* Texte= NULL; 
    if(NULL == (Texte = fopen("chaines", "r"))) 
    { // then fopen failed 
     perror("fopen failed for chaines for read"); 
     free(Tab_Texte); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, fopen successful 

    if(0 != fseek(Texte, 0, SEEK_END)) 
    { // then fseek failed 
     perror("fseek for end of file failed"); 
     fclose(Texte); 
     free(Tab_Texte); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, fseek successful 

    if(-1L == (Tab_Texte->Taille_C=ftell(Texte))) 
    { // then ftell failed 
     perror("ftell failed"); 
     fclose(Texte); 
     free(Tab_Texte); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, ftell successful 

    if(0 != fseek(Texte, 0, SEEK_SET)) 
    { // then fseek failed 
     perror("fseek for start of file failed"); 
     fclose(Texte); 
     free(Tab_Texte); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, fseek successful 


    Tab_Texte->Lachaine=NULL; 
    if(NULL == (Tab_Texte->Lachaine=malloc(Tab_Texte->Taille_C))) 
    { // then, malloc failed 
     perror("malloc failed for file size"); 
     fclose(Texte); 
     free(Tab_Texte); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, malloc successful 

    if(1 != fread(Tab_Texte->Lachaine, sizeof(Tab_Texte->Taille_C), 1 , Texte)) 
    { // fread failed 
     perror("fread for whole file failed"); 
     fclose(Texte); 
     free(Tab_Texte->Lachaine); 
     free(Tab_Texte); 
     exit(EXIT_FAILURE); 
    } 

    // implied else, fread successful 

    printf("%s",Tab_Texte->Lachaine); 

    // cleanup 
    fclose(Texte); 
    free(Tab_Texte->Lachaine); 
    free(Tab_Texte); 

    return 0; 
} // end function: main 
+0

請修正文本格式 –

+0

好吧,沒有冒犯,但在建議'消除雜亂無章'之前,請考慮將其應用於您的帖子。 –