No segmentation fault for accessing out of bound memory

只谈情不闲聊 提交于 2021-02-11 14:19:36

问题


I'm not a good English speaker.

so in my program I want to copy a text who exists in a txt file to an array.

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;
}

Here everything works great and when I change

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

with ( for example )

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

It works always, It suppose to show me a segmentation fault because sizeof(char)*Tab_Texte->Taille_C - 10 is shorter than sizeof(char)*Tab_Texte->Taille_C so than the text in the file.

Can you tell me why it always works?


回答1:


What you're experiencing is called undefined behavior.

  • Accessing past the allocated memory
  • Using a not-null terminated char array as string
  • supplying invalid file pointer

all [any] of these will result in undefined behavior and the side effect may be a segmentation fault, but it's not guaranteed.

Please

  1. Check for the success of fopen() before using the returned pointer
  2. null-terminate a char array to use it as a string
  3. free() the allocated memory after the usage is over.
  4. Do not cast the return value of malloc()/ calloc().



回答2:


The reason why it works always is because what you describe is undefined behavior so it's not really defined what should happen.

In some situations it may lead to a segmentation fault but not always. So your always is really sometimes, but it turns out the conditions haven't been the right ones for the segmentation fault to happen.

Consider the following fixes to your code:

  1. You should not do this

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

    since your Tab_Texte->Lachaine is not null terminated

  2. You can try to do it like this

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

    but generally you never check for every single function that returns null on failure in your code.

    For example

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

    also applies for malloc, and you don't need to cast malloc, read this

  3. You should free the result of malloc when you no longer need it.




回答3:


You will get a segfault is you read or write to memory that is not allocated for your program. If you misuse malloc, you may not get a segfault, depending on the way the underlying operating system loads your program into memory. In that case, you may be writing or reading from your own memory, but in different locations, potentially overwriting other variables.




回答4:


// the reason a seg fault event did not occur is because // the code is using the contents of the field: Tab_Texte->Taille_C // which is the full size of the file // (so no problem unless file has less than 10 bytes)

//eliminate a lot of clutter in your code via proper definition of a struct rather that a typedef

//do not cast the returned value from malloc (and family)

//check the returned value from malloc to assure successful operation

//check the returned value from fopen to assure successful operation

//check the returned value from fseek to assure successful operation

//check the returned value from ftell to assure successful operation

//cleanup when exiting program, including free for malloc'd areas, closing files, etc

//check the returned value from fread to assure successful operation

#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


来源:https://stackoverflow.com/questions/27730460/no-segmentation-fault-for-accessing-out-of-bound-memory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!