Thread: Dynamic allocation (I thought it would crash)

  1. #1
    Registered User Baaaah!'s Avatar
    Join Date
    Oct 2005
    Location
    UK
    Posts
    23

    Dynamic allocation (I thought it would crash)

    I've been trying to learn a bit about dynamic allocation in my noobish way, and I decided to see what would happen if I deliberately tried to cram too much data into a memory block that is too small to contain it all. Ironically the program seems to function correctly, printing out the full array, even though I've tried to make it overload. I can't figure out why.

    Code:
    /* Dynamic memory allocation */
    
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
       char size[5];   // Array deliberately set too small
       int *memory_block;
       int i;
       char word[] = "abcdefghijklmnopqrs";
       char c;
    
       /* Allocate memory defined by char array 'size' */
       memory_block = malloc(sizeof(size));
       
       /* Check for allocation failure */
       if(memory_block == NULL)
       {
          printf("Allocation Failed.\n");
          exit(EXIT_FAILURE);
       }else
          printf("Memory Allocated.\n");
    
       /* Copy data stored in 'word' into 'memory_block' */
       for(i = 0; word[i]; i++)
       {
       memory_block[i] = word[i];
       printf("%c\n", memory_block[i]);   
       }
    
       /* Return memory to heap */
       free(memory_block);
    
       /* Exit */
       printf("Press 'q' to exit:");
       if((c = _getch()) == 'q')
          return 0;
    }
    Output:

    Memory Allocated
    a
    b
    c
    d
    e
    f
    ............
    s
    Press 'q' to exit:
    Last edited by Baaaah!; 11-30-2005 at 05:39 AM.

  2. #2
    Bond sunnypalsingh's Avatar
    Join Date
    Oct 2005
    Posts
    162
    It did crash in my compiler(VC6.0)...behaviour isundefined

  3. #3
    Registered User
    Join Date
    Jun 2005
    Location
    Stockholm, Sweden
    Posts
    64
    The behaviour is not undefined. You write past the end of the allocated memory, the language and/or compiler can't control what happens then.

    If you are lucky you write onto unused memory and nothing happens. If you're unlucky you overwrite data in use by another application and your computer crashes.

  4. #4
    Registered User Baaaah!'s Avatar
    Join Date
    Oct 2005
    Location
    UK
    Posts
    23
    The compiler I'm using is MinGW. I've just tried it with the Digital Mars complier and it works with that as well. Confused.

  5. #5
    Registered User Baaaah!'s Avatar
    Join Date
    Oct 2005
    Location
    UK
    Posts
    23
    kungtotte - ah I see, thanks . Is there a way to stop it writing into unallocated memory?

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by kungtotte
    The behaviour is not undefined. You write past the end of the allocated memory, the language and/or compiler can't control what happens then.
    Just what do you think "undefined" means? Oh, and to clarify, yes, it is undefined.


    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    Registered User
    Join Date
    Jun 2005
    Location
    Stockholm, Sweden
    Posts
    64
    Well, when we are talking about defined or undefined behaviour with regards to C we are normally referring to the C language standard, yes? And based on the content in this thread, that is what I assumed the original poster was referring to as well.

    The C language standard doesn't specify which endianess that the operating system uses, so does that mean that endianess is undefined in general?

  8. #8
    Bond sunnypalsingh's Avatar
    Join Date
    Oct 2005
    Posts
    162
    I don't know what endianess you are talking about...i am not sure if it is related to it or not...On same system it works on one compiler(gcc) and does not works on other(VC6.0).It is undefined.

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    You were saying that writing past the end of allocated space, in essence, any misuse of pointer, is somehow defined:
    Quote Originally Posted by kungtotte
    The behaviour is not undefined. You write past the end of the allocated memory, the language and/or compiler can't control what happens then.
    It is undefined. You in your statement say the language or compiler can't control what happens, and yet somehow you think it's defined.
    Quote Originally Posted by kungtotte
    The C language standard doesn't specify which endianess that the operating system uses, so does that mean that endianess is undefined in general?
    The C language doesn't care anything about endianness. It doesn't matter. That's an implementation specific issue. It has nothing to do with the language itself and therefore isn't a language issue at all.


    Quzah.
    Hope is the first step on the road to disappointment.

  10. #10
    Registered User KidA's Avatar
    Join Date
    Nov 2005
    Location
    Ohio, USA
    Posts
    26
    Unfortunately, C has no built-in array bounds checking, or any built-in checking on pointer arithmetic.

    This has caused me numerous headaches, even with a statically allocated string, when I suddenly decide to use it to hold more data but forget to increase its declared size.

    Sometimes you exceed the limits and it performs just fine, but in my experience the result is typically a nice general protection fault that seems pretty "random" in cause. The first couple times this happened the result was a great deal of panic on my part. Now I know if I bring a program to its knees like that it's likely because I'm doing some kind of faulty pointer logic.

    But now you can brag that even when you're *trying* to, you can't write a bad program!

  11. #11
    Me -=SoKrA=-'s Avatar
    Join Date
    Oct 2002
    Location
    Europe
    Posts
    448
    >It is undefined. You in your statement say the language or compiler can't control what
    >happens, and yet somehow you think it's defined.

    It's undefined in that you don't know what's going to happen, but it's definately(sp?) not undefined by the C standard.

    malloc() gives you a piece of memory which you're free to use, but you can write to any address you feel like (wether the OS will let you is another matter), but that doesn't mean you know what's going to happen as a result of you writing to a particular address.

    The C standards clearly states what will happen when you do array[random_num] = 0; it will set the byte/bytes/whatever in address (array + random_num * sizeof(*array)) to zero. The concequences of you doing so is another matter.

    The sizeof(*array) may be sizeof(array), but I think here the array would degrade into a pointer and thus the '*' is needed.

    >The C language doesn't care anything about endianness. It doesn't matter.

    Neither does it care about illegal memory access.
    SoKrA-BTS "Judge not the program I made, but the one I've yet to code"
    I say what I say, I mean what I mean.
    IDE: emacs + make + gcc and proud of it.

  12. #12
    Registered User Baaaah!'s Avatar
    Join Date
    Oct 2005
    Location
    UK
    Posts
    23
    Quote Originally Posted by KidA
    But now you can brag that even when you're *trying* to, you can't write a bad program!
    if only that were true.

    Thanks for the responses. I get most of it - not all . It's clearer than before anyway.

  13. #13
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Quote Originally Posted by -=SoKrA=-
    >It is undefined. You in your statement say the language or compiler can't control what
    >happens, and yet somehow you think it's defined.

    It's undefined in that you don't know what's going to happen, but it's definately(sp?) not undefined by the C standard.

    malloc() gives you a piece of memory which you're free to use, but you can write to any address you feel like (wether the OS will let you is another matter), but that doesn't mean you know what's going to happen as a result of you writing to a particular address.

    The C standards clearly states what will happen when you do array[random_num] = 0; it will set the byte/bytes/whatever in address (array + random_num * sizeof(*array)) to zero. The concequences of you doing so is another matter.

    The sizeof(*array) may be sizeof(array), but I think here the array would degrade into a pointer and thus the '*' is needed.

    >The C language doesn't care anything about endianness. It doesn't matter.

    Neither does it care about illegal memory access.

    Are you kidding? Please don't try to say what the standard does or does not say without actually looking at it. From the standard, section J.2, page 490:
    J.2 Undefined behavior
    1 The behavior is undefined in the following circumstances:
    ...
    Addition or subtraction of a pointer into, or just beyond, an array object and an
    integer type produces a result that does not point into, or just beyond, the same array
    object (6.5.6).
    Since a[n] is the same as *((a)+(n)) it's pointer addition.
    If you understand what you're doing, you're not learning anything.

  14. #14
    Me -=SoKrA=-'s Avatar
    Join Date
    Oct 2002
    Location
    Europe
    Posts
    448
    Quote Originally Posted by itsme86
    Are you kidding? Please don't try to say what the standard does or does not say without actually looking at it. From the standard, section J.2, page 490:
    Ah, sorry, from what I've read, it I've been always under the impression that the standard doesn't care. Obviously I was wrong.
    Quote Originally Posted by itsme86
    Since a[n] is the same as *((a)+(n)) it's pointer addition.
    Yeah, but why don't quote three entries later? In my (newly acquired) copy of the standard, J.2, page 493:
    Quote Originally Posted by ISO/IEC 9899:1999
    - An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue a[1][7] given the declaration int a[4][5] )(6.5.6).
    What I don't quite get is this:
    integer type produces a result that does not point into, or just beyond, the same array
    So, if the pointer points to just beyond the array, it's defined? And what is just beyond, anyway?
    SoKrA-BTS "Judge not the program I made, but the one I've yet to code"
    I say what I say, I mean what I mean.
    IDE: emacs + make + gcc and proud of it.

  15. #15
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Yes, that is defined. What "just beyond" means is pointing to the element that is one element past the actual end of the array. For example, an array with 10 elements lets you check for comparison to see if you've reached array[ 10 ]. You cannot access that "element", since it doesn't actually exist, but you can use that address point as a comparison. For example, a valid point to test for to stop a loop.
    Code:
    int array[ 10 ];
    int *ptr, *end;
    
    for( ptr = array, end = array + 10; ptr < end; ptr++ )
    {
        ...
    }
    You can't access array[ 10 ], but you can test to see if you're at that spot.


    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A question related to dynamic memory allocation
    By spiit231 in forum C Programming
    Replies: 2
    Last Post: 03-11-2008, 12:25 AM
  2. Dynamic allocation of 2 dim. arrays in classes
    By circuitbreaker in forum C++ Programming
    Replies: 4
    Last Post: 02-10-2008, 12:13 PM
  3. Replies: 16
    Last Post: 01-01-2008, 04:07 PM
  4. Find Size Of Dynamic Memory Allocation?
    By appleGuy in forum C++ Programming
    Replies: 7
    Last Post: 06-17-2007, 09:34 AM
  5. Dynamic memory allocation...
    By dicorr in forum C Programming
    Replies: 1
    Last Post: 06-24-2006, 03:59 AM