Why no segmentation fault

Discussion in 'C Programming' started by Christian Christmann, Mar 26, 2006.

  1. Hi,

    I'm wondering why this program does not crash with a segmentation
    fault:

    #include <malloc.h>
    #include <string.h>
    #include <stdio.h>

    int main()
    {
    char *array;

    array = (char*)malloc(10 * sizeof(char) );
    if ( array == NULL )
    exit( 0 );

    strcpy( array, "11223456789\0");

    printf( "\narray[11]: %c\n", array[11] )

    return 0;
    }

    I allocate space for 10 characters on the system heap and then copy
    a string of size 12 into the allocated space. Why does the program not
    crash?
    My understanding was so far:
    malloc request some new free space on the system heap. So, first the
    program memory manager is consulted to check if it is already assigned
    some free space by the operating system that might be suitable for the
    malloc request. If so, this memory segment is used. Otherwise, the
    request is directed to the OS that provides some new free memory that
    is now assigned to this program (process) and used for the malloc memory
    allocation. However, when I call "strcpy( array, "11223456789\0")" I
    write the first 10 characters to the allocated memory area.The
    remaining 2 characters exceed the memory area I was granted access to
    and are tried to be written to memory I have no write access to. That
    illegal memory access should be noticed by the OS that terminates the
    program with a segmentation fault.

    Furthermore, my printf should also crash the program since I
    illegally attempt to read from memory I have no access to.

    Thank you.

    Chris
    Christian Christmann, Mar 26, 2006
    #1
    1. Advertising

  2. On 2006-03-26, Christian Christmann <> wrote:
    > Hi,
    >
    > I'm wondering why this program does not crash with a segmentation
    > fault:
    >
    > #include <malloc.h>
    > #include <string.h>
    > #include <stdio.h>
    >
    > int main()
    > {
    > char *array;
    >
    > array = (char*)malloc(10 * sizeof(char) );
    > if ( array == NULL )
    > exit( 0 );
    >
    > strcpy( array, "11223456789\0");
    >
    > printf( "\narray[11]: %c\n", array[11] )
    >
    > return 0;
    > }
    >


    There is no guarentee that HW will catch all such illegal memory
    accesses. There are not (always) runtime checks in languages to check
    for out of bounds : it is one of the efficiencies of C that it assumes
    the programmer will do the necessary bounds checks. Writing over
    "illegal" memory is, I believe, "undefined" but most certainly bad
    practice and most certainly will lead to nasties cropping up at a
    later date if nto immediately.

    I velieve it is legal to reference one unit of storage past the
    "malloc"ed area, but I'm sure someone will provide more info on that.
    Richard G. Riley, Mar 26, 2006
    #2
    1. Advertising

  3. Christian Christmann

    santosh Guest

    Christian Christmann wrote:
    > Hi,
    >
    > I'm wondering why this program does not crash with a segmentation
    > fault:
    >
    > #include <malloc.h>


    Non-standard header. Should include stdlib.h instead.

    > #include <string.h>
    > #include <stdio.h>
    >
    > int main()


    A better form is int main(void)

    > {
    > char *array;
    >
    > array = (char*)malloc(10 * sizeof(char) );


    Don't cast the return value of malloc. A better form of the above
    statement is:
    array = malloc(10 * sizeof *array);

    This also has the side effect that if you ever change the base type,
    (char here), you won't have to modify this statement.

    > if ( array == NULL )
    > exit( 0 );


    exit(EXIT_SUCCESS); or exit(EXIT_FAILURE) would be more portable though
    zero is always a portable return value to indicate successfull
    termination.

    > strcpy( array, "11223456789\0");
    >
    > printf( "\narray[11]: %c\n", array[11] )
    >
    > return 0;
    > }
    >
    > I allocate space for 10 characters on the system heap and then copy
    > a string of size 12 into the allocated space. Why does the program not
    > crash?
    > My understanding was so far:
    > malloc request some new free space on the system heap. So, first the
    > program memory manager is consulted to check if it is already assigned
    > some free space by the operating system that might be suitable for the
    > malloc request. If so, this memory segment is used. Otherwise, the
    > request is directed to the OS that provides some new free memory that
    > is now assigned to this program (process) and used for the malloc memory
    > allocation. However, when I call "strcpy( array, "11223456789\0")" I
    > write the first 10 characters to the allocated memory area.The
    > remaining 2 characters exceed the memory area I was granted access to
    > and are tried to be written to memory I have no write access to. That
    > illegal memory access should be noticed by the OS that terminates the
    > program with a segmentation fault.
    >
    > Furthermore, my printf should also crash the program since I
    > illegally attempt to read from memory I have no access to.


    Your program writes past the end of the array and doing so, invokes
    undefined behaviour. Wether it eventually crashes or not is
    implementation defined. In any case, anything can happen as per the C
    standard. It might apparently continue running normally, (like your
    case, which could be because, your library memory manager reserved more
    memory as a part of your process, and that they just happen to lie past
    your allocated chunk.), or it might misbehave later or dump core
    immediately.

    It doesn't matter. Once you've created undefined behaviour, anything
    might happen.
    santosh, Mar 26, 2006
    #3
  4. Christian Christmann

    Eric Sosman Guest

    santosh wrote:
    >
    > Your program writes past the end of the array and doing so, invokes
    > undefined behaviour. Wether it eventually crashes or not is
    > implementation defined. [...]


    <pedantry>

    It's not even implementation-defined; the implementation
    has no obligation to document the consequences. Undefined is
    undefined, and there's an end on't.

    </pedantry>

    --
    Eric Sosman
    lid
    Eric Sosman, Mar 26, 2006
    #4
  5. Christian Christmann

    santosh Guest

    Eric Sosman wrote:
    > santosh wrote:
    > > Your program writes past the end of the array and doing so, invokes
    > > undefined behaviour. Wether it eventually crashes or not is
    > > implementation defined. [...]

    >
    > <pedantry>
    > It's not even implementation-defined; the implementation
    > has no obligation to document the consequences. Undefined is
    > undefined, and there's an end on't.
    > </pedantry>


    Thanks pedantic point duly noted and filed!
    santosh, Mar 26, 2006
    #5
  6. Christian Christmann

    Jorgen Grahn Guest

    On 26 Mar 2006 10:03:10 -0800, santosh <> wrote:
    > Christian Christmann wrote:

    ....
    >> {
    >> char *array;
    >>
    >> array = (char*)malloc(10 * sizeof(char) );

    >
    > Don't cast the return value of malloc. A better form of the above
    > statement is:
    > array = malloc(10 * sizeof *array);
    >
    > This also has the side effect that if you ever change the base type,
    > (char here), you won't have to modify this statement.


    Yes; casting malloc()'s return value became obsolete when void * was
    introduced, some twenty years ago.

    As a side note, typing "sizeof(char)" is pointless, since its value is, by
    definition, 1.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Ph'nglui mglw'nafh Cthulhu
    \X/ snipabacken.dyndns.org> R'lyeh wgah'nagl fhtagn!
    Jorgen Grahn, Mar 26, 2006
    #6
  7. "santosh" <> writes:
    > Christian Christmann wrote:

    [...]
    > This also has the side effect that if you ever change the base type,
    > (char here), you won't have to modify this statement.
    >
    >> if ( array == NULL )
    >> exit( 0 );

    >
    > exit(EXIT_SUCCESS); or exit(EXIT_FAILURE) would be more portable though
    > zero is always a portable return value to indicate successfull
    > termination.


    exit(0) is exactly as portable as exit(EXIT_SUCCESS); both are defined
    to return a status that indicates successful termination (though not
    necessarily the same status).

    But since this particular exit() is executed only on a failure of
    malloc(), exit(EXIT_FAILURE) would make more sense. (Note that
    exit(1), unlike exit(0), is *not* portable.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Mar 26, 2006
    #7
  8. Christian Christmann

    santosh Guest

    Keith Thompson wrote:
    > "santosh" <> writes:

    <snip>
    > > exit(EXIT_SUCCESS); or exit(EXIT_FAILURE) would be more portable though
    > > zero is always a portable return value to indicate successfull
    > > termination.

    >
    > exit(0) is exactly as portable as exit(EXIT_SUCCESS); both are defined
    > to return a status that indicates successful termination (though not
    > necessarily the same status).


    Err, don't you mean:
    "...though not necessarily the same value."
    above?

    <snip>
    santosh, Mar 26, 2006
    #8
  9. "santosh" <> writes:
    > Keith Thompson wrote:
    >> "santosh" <> writes:

    > <snip>
    >> > exit(EXIT_SUCCESS); or exit(EXIT_FAILURE) would be more portable though
    >> > zero is always a portable return value to indicate successfull
    >> > termination.

    >>
    >> exit(0) is exactly as portable as exit(EXIT_SUCCESS); both are defined
    >> to return a status that indicates successful termination (though not
    >> necessarily the same status).

    >
    > Err, don't you mean:
    > "...though not necessarily the same value."
    > above?


    No, I meant status. It's also true that it's not necessarily the same
    value.

    The standard says:

    Finally, control is returned to the host environment. If the
    value of status is zero or EXIT_SUCCESS, an implementation-defined
    form of the status _successful termination_ is returned. If the
    value of status is EXIT_FAILURE, an implementation-defined form of
    the status _unsuccessful termination_ is returned. Otherwise the
    status returned is implementation-defined.

    EXIT_SUCCESS, EXIT_FAILURE, and 0 are values of type int that can be
    passed to the exit() function. A "status" is a vaguely-defined thing
    that's seen by the host environment; it isn't necessarily a value,
    particularly an int value, in the sense used within a C program. (The
    fact that parameter to exit() is also called "status" is potentially
    confusing.)

    If EXIT_SUCCESS==0, then presumably both exit(EXIT_SUCCESS) and
    exit(0) return the same "status" to the environment. If
    EXIT_SUCCESS!=0, then exit(EXIT_SUCCESS) and exit(0) may or may not
    return the same "status" to the environment.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Mar 26, 2006
    #9
  10. Christian Christmann

    Flash Gordon Guest

    santosh wrote:
    > Christian Christmann wrote:


    <snip>

    >> if ( array == NULL )
    >> exit( 0 );

    >
    > exit(EXIT_SUCCESS); or exit(EXIT_FAILURE) would be more portable though
    > zero is always a portable return value to indicate successfull
    > termination.


    <snip>

    As well as the comments others have made, exit(EXIT_SUCCESS) and
    exit(EXIT_FAILURE) are no more portable than exit(0) since all three are
    completely portable. Any other value and zero and I would have agreed.
    However, in this case exit(EXIT_FAILURE) would have been far better
    style since the program has failed.
    --
    Flash Gordon, living in interesting times.
    Web site - http://home.flash-gordon.me.uk/
    comp.lang.c posting guidelines and intro:
    http://clc-wiki.net/wiki/Intro_to_clc
    Flash Gordon, Mar 26, 2006
    #10
  11. Christian Christmann

    Flash Gordon Guest

    Richard G. Riley wrote:

    <snip>

    > I velieve it is legal to reference one unit of storage past the
    > "malloc"ed area, but I'm sure someone will provide more info on that.


    It is legal to create a pointer to one past the end, but it is not legal
    to dereference that pointer.
    --
    Flash Gordon, living in interesting times.
    Web site - http://home.flash-gordon.me.uk/
    comp.lang.c posting guidelines and intro:
    http://clc-wiki.net/wiki/Intro_to_clc
    Flash Gordon, Mar 26, 2006
    #11
  12. Christian Christmann

    santosh Guest

    Keith Thompson wrote:
    > "santosh" <> writes:
    > > Keith Thompson wrote:
    > >> exit(0) is exactly as portable as exit(EXIT_SUCCESS); both are defined
    > >> to return a status that indicates successful termination (though not
    > >> necessarily the same status).

    > >
    > > Err, don't you mean:
    > > "...though not necessarily the same value."
    > > above?

    >
    > No, I meant status. It's also true that it's not necessarily the same
    > value.

    .... snip ...

    > If EXIT_SUCCESS==0, then presumably both exit(EXIT_SUCCESS) and
    > exit(0) return the same "status" to the environment. If
    > EXIT_SUCCESS!=0, then exit(EXIT_SUCCESS) and exit(0) may or may not
    > return the same "status" to the environment.


    Okay, so both exit(0) and exit(EXIT_SUCCESS) need not return the same
    "status" to the host environment although they both *indicate*
    successful program termination. Got it now, just that your wording in
    your first reply to me seemed contradictory.
    santosh, Mar 26, 2006
    #12
  13. Christian Christmann

    santosh Guest

    Keith Thompson wrote:
    > "santosh" <> writes:
    > > Keith Thompson wrote:
    > >> exit(0) is exactly as portable as exit(EXIT_SUCCESS); both are defined
    > >> to return a status that indicates successful termination (though not
    > >> necessarily the same status).

    > >
    > > Err, don't you mean:
    > > "...though not necessarily the same value."
    > > above?

    >
    > No, I meant status. It's also true that it's not necessarily the same
    > value.

    .... snip ...

    Would it not be absurd for an implementation to return "status" values
    of different kinds for exit(0) and exit(EXIT_SUCCESS), though the
    standard does not disallow it? I mean, since both forms of exit() are
    semantically identical, what would be gained in returning different
    kinds of "status" values to the host environment? Are you aware of any
    actual implementations that do this?
    santosh, Mar 26, 2006
    #13
  14. Flash Gordon <> writes:
    > Richard G. Riley wrote:
    >
    > <snip>
    >
    >> I velieve it is legal to reference one unit of storage past the
    >> "malloc"ed area, but I'm sure someone will provide more info on that.

    >
    > It is legal to create a pointer to one past the end, but it is not
    > legal to dereference that pointer.


    "not legal" meaning that it invokes undefined behavior (the
    implementation is not required to diagnose it).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Mar 26, 2006
    #14
  15. "Christian Christmann" <> wrote in message
    news:4426cee1$0$17571$-online.net...
    > I'm wondering why this program does not crash with a segmentation
    > fault:

    ....
    > Furthermore, my printf should also crash the program since I
    > illegally attempt to read from memory I have no access to.


    Your program invokes undefined behavior. Undefined behavior can take many
    forms, including doing nothing or doing exactly what the programmer
    mistakenly expects.

    Just because your machine traps on some undefined operations does not mean
    it always will.

    S

    --
    Stephen Sprunk "Stupid people surround themselves with smart
    CCIE #3723 people. Smart people surround themselves with
    K5SSS smart people who disagree with them." --Aaron Sorkin

    *** Free account sponsored by SecureIX.com ***
    *** Encrypt your Internet usage with a free VPN account from http://www.SecureIX.com ***
    Stephen Sprunk, Mar 26, 2006
    #15
  16. "santosh" <> writes:
    > Keith Thompson wrote:
    >> "santosh" <> writes:
    >> > Keith Thompson wrote:
    >> >> exit(0) is exactly as portable as exit(EXIT_SUCCESS); both are defined
    >> >> to return a status that indicates successful termination (though not
    >> >> necessarily the same status).
    >> >
    >> > Err, don't you mean:
    >> > "...though not necessarily the same value."
    >> > above?

    >>
    >> No, I meant status. It's also true that it's not necessarily the same
    >> value.

    > ... snip ...
    >
    > Would it not be absurd for an implementation to return "status" values
    > of different kinds for exit(0) and exit(EXIT_SUCCESS), though the
    > standard does not disallow it? I mean, since both forms of exit() are
    > semantically identical, what would be gained in returning different
    > kinds of "status" values to the host environment? Are you aware of any
    > actual implementations that do this?


    I suppose it would be absurd, but it would be perfectly valid. No, I
    don't know of any implementations that do this. VMS is the obvious
    candidate, but it defines EXIT_SUCCESS as 0, at least in the version I
    have access to.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Mar 26, 2006
    #16
  17. Christian Christmann

    Mark Guest

    On Sun, 26 Mar 2006 19:33:40 +0200, Christian Christmann wrote:

    > Hi,
    >
    > I'm wondering why this program does not crash with a segmentation fault:
    >
    > #include <malloc.h>
    > #include <string.h>
    > #include <stdio.h>
    >
    > int main()
    > {
    > char *array;
    >
    > array = (char*)malloc(10 * sizeof(char) ); if ( array == NULL )
    > exit( 0 );
    >
    > strcpy( array, "11223456789\0");
    >
    > printf( "\narray[11]: %c\n", array[11] )
    >
    > return 0;
    > }
    >
    > I allocate space for 10 characters on the system heap and then copy a
    > string of size 12 into the allocated space. Why does the program not
    > crash?
    > My understanding was so far:
    > malloc request some new free space on the system heap. So, first the
    > program memory manager is consulted to check if it is already assigned
    > some free space by the operating system that might be suitable for the
    > malloc request. If so, this memory segment is used. Otherwise, the
    > request is directed to the OS that provides some new free memory that is
    > now assigned to this program (process) and used for the malloc memory
    > allocation. However, when I call "strcpy( array, "11223456789\0")" I
    > write the first 10 characters to the allocated memory area.The remaining
    > 2 characters exceed the memory area I was granted access to and are
    > tried to be written to memory I have no write access to. That illegal
    > memory access should be noticed by the OS that terminates the program
    > with a segmentation fault.
    >
    > Furthermore, my printf should also crash the program since I illegally
    > attempt to read from memory I have no access to.
    >
    >
    >

    Your malloc prolly allocates (multiples of) a fixed size block (a page?)
    at a time from the OS from which it gives you a piece at a time every time
    you malloc. If you've malloced it all up malloc will ask the OS for
    more.... This is more efficient then having to ask the OS every time you
    malloc a byte.

    So even though you didn't get the memory from malloc, as long as you stay
    inside the memory malloc allocated from the OS you wont cause a
    segfault. The OS will happily let you ****-up, as long a you do it in
    your own home/process :)

    Mark.
    Mark, Mar 27, 2006
    #17
  18. On 26 Mar 2006 13:02:10 -0800, in comp.lang.c , "santosh"
    <> wrote:

    >Would it not be absurd for an implementation to return "status" values
    >of different kinds for exit(0) and exit(EXIT_SUCCESS), though the
    >standard does not disallow it?


    There are different kinds of success, though, aren't there?

    >I mean, since both forms of exit() are
    >semantically identical, what would be gained in returning different
    >kinds of "status" values to the host environment?


    eg
    exit (success-and-missed-object-in-water)
    exit (success-and-beached-on-iceberg)
    exit(success-but-ship-sank-anyway-due-to-outside-factors)

    >Are you aware of any
    >actual implementations that do this?


    I strongly suspect VMS lets you have a forest of possible different
    "it worked" results.
    0 = VMS-I-SUCCESS successful programme termination
    64 = VMS-I-SUCCESS successful cluster shutdown
    128 = VMS-I-SUCCESS successfully ejected the warp core
    :)

    Mark McIntyre
    --
    "Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are,
    by definition, not smart enough to debug it."
    --Brian Kernighan
    Mark McIntyre, Mar 27, 2006
    #18
  19. Mark McIntyre <> writes:
    > On 26 Mar 2006 13:02:10 -0800, in comp.lang.c , "santosh"
    > <> wrote:
    >
    >>Would it not be absurd for an implementation to return "status" values
    >>of different kinds for exit(0) and exit(EXIT_SUCCESS), though the
    >>standard does not disallow it?

    >
    > There are different kinds of success, though, aren't there?


    Maybe. Some systems define only one kind of success (corresponding to
    exit(0)).

    [snip]

    >>Are you aware of any
    >>actual implementations that do this?

    >
    > I strongly suspect VMS lets you have a forest of possible different
    > "it worked" results.
    > 0 = VMS-I-SUCCESS successful programme termination
    > 64 = VMS-I-SUCCESS successful cluster shutdown
    > 128 = VMS-I-SUCCESS successfully ejected the warp core
    > :)


    Actually, odd values denote success and even values denote errors
    (which is why VMS has to translate exit(0) into a failure indication,
    and exit(1) actually denotes success). But yes, there are many
    different kinds of both success and failure in VMS (but no portable
    way to specify them in C).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Mar 27, 2006
    #19
  20. On Mon, 27 Mar 2006 21:13:46 GMT, in comp.lang.c , Keith Thompson
    <> wrote:

    >Actually, odd values denote success and even values denote errors
    >(which is why VMS has to translate exit(0) into a failure indication,
    >and exit(1) actually denotes success).


    I think you may have this backwards, since I recall being able to
    compile perfectly normal C code with VAX-C, but its at least five
    years since I last programmed on a Vax so...

    Mark McIntyre
    --
    "Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are,
    by definition, not smart enough to debug it."
    --Brian Kernighan
    Mark McIntyre, Mar 27, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. VB
    Replies:
    3
    Views:
    5,215
    Ron Natalie
    Jan 15, 2005
  2. Anks

    Why segmentation fault

    Anks, Sep 13, 2003, in forum: C Programming
    Replies:
    3
    Views:
    585
    The Real OS/2 Guy
    Sep 14, 2003
  3. Jay  donnell

    why am I getting a segmentation fault?

    Jay donnell, Jan 21, 2005, in forum: Python
    Replies:
    6
    Views:
    376
    John Machin
    Jan 22, 2005
  4. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,842
    Smokey Grindel
    Dec 2, 2006
  5. Polar
    Replies:
    11
    Views:
    683
    Polar
    Aug 9, 2004
Loading...

Share This Page