Thread: Why does this crash first when memmory is freed?

  1. #1
    Registered User
    Join Date
    Sep 2007
    Posts
    26

    Why does this crash first when memmory is freed?

    Okay let's take a look at this wrong scanf-implementation:
    Code:
    #include <stdio.h>
    
    int main(void) {
         
           char *buff[20];
    
           scanf("%s",buff);
           printf("%s\n",buff);
     
           return 0;
    }
    If I take now a large enough input to write over the basepointer or even eip , I'm getting a segfault. The correct usage would be of course scanf("%20s",buff);.

    But now take a look at this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void) {
         
           char *buff;
    
           buff = malloc(20);
           scanf("%s",buff);
      
           printf("%s\n",buff);
           
           return 0;
    }
    No matter how large the input was it never crashed in my tests but read everything and printed everything out again. Just if I free the memory after the printf-instruction again with free(buff); I'm crashing:
    Code:
    *** glibc detected *** ./hello: free(): invalid next size (fast): 0x0804a008 ***
    ======= Backtrace: =========
    /lib/tls/i686/cmov/libc.so.6[0xb7e167cd]
    /lib/tls/i686/cmov/libc.so.6(cfree+0x90)[0xb7e19e30]
    ./hello[0x804845d]
    /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xdc)[0xb7dc4ebc]
    ./hello[0x8048391]
    ======= Memory map: ========
    08048000-08049000 r-xp 00000000 fe:00 1661139    /home/user/Desktop/hello
    08049000-0804a000 rw-p 00000000 fe:00 1661139    /home/user/Desktop/hello
    0804a000-0806b000 rw-p 0804a000 00:00 0          [heap]
    b7c00000-b7c21000 rw-p b7c00000 00:00 0 
    b7c21000-b7d00000 ---p b7c21000 00:00 0 
    b7dae000-b7daf000 rw-p b7dae000 00:00 0 
    b7daf000-b7eea000 r-xp 00000000 08:05 456891     /lib/tls/i686/cmov/libc-2.5.so
    b7eea000-b7eeb000 r--p 0013b000 08:05 456891     /lib/tls/i686/cmov/libc-2.5.so
    b7eeb000-b7eed000 rw-p 0013c000 08:05 456891     /lib/tls/i686/cmov/libc-2.5.so
    b7eed000-b7ef0000 rw-p b7eed000 00:00 0 
    b7ef5000-b7f00000 r-xp 00000000 08:05 423552     /lib/libgcc_s.so.1
    b7f00000-b7f01000 rw-p 0000a000 08:05 423552     /lib/libgcc_s.so.1
    b7f01000-b7f05000 rw-p b7f01000 00:00 0 
    b7f05000-b7f1e000 r-xp 00000000 08:05 423511     /lib/ld-2.5.so
    b7f1e000-b7f20000 rw-p 00019000 08:05 423511     /lib/ld-2.5.so
    bfc09000-bfc1e000 rw-p bfc09000 00:00 0          [stack]
    ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
    Aborted
    How much space will actually be there on the heap until something serious happens? Why is it crashing when freed?

  2. #2
    Registered User
    Join Date
    Sep 2007
    Posts
    69
    I am just a beginner in C but when I use scanf, I include a "&".

    So this:

    Code:
    scanf("%s",buff);
    I would write:

    Code:
    scanf("%s", &buff);
    Im probably wrong but if someone could point out to me, when a "&" is used and when not. (No point in creating a new thread).

  3. #3
    Registered User
    Join Date
    Sep 2007
    Posts
    26
    why not opening another thread????

    buff is a pointer in my code and &buff is a memory adress to the content of buff, so both are the same in this case.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    First to answer lilcoders question:

    When you allocate memory through (for example) malloc, it will give you a block of memory.

    The way memory protection works is that it's based on a "page-table". The page-table is (for reduction of overhead) split into regions of 4KB each - called pages. When you call malloc, you are given a chunk of memory within a page (or crossing over a page-boundary perhaps). This may be at the beginning of a page, at the end of a page, or in middle of a page. There's no way to determine which it will be without detailed knowledge of what has been going on in the system before this particular call to malloc. There's also no guarantee that the page after the one you got memory from is not also valid - perhaps even several megabytes of memory is valid after the memory address malloc returned.

    So, only when you go to free your memory is it discovered that the data in the block of memory is invalid - this is because some consistancy checks in free (presumably it tries to merge freed blocks, and in so, it's looking at the next block of memory after then one you freed, and something "doesn't match up", so it fails.

    [It is even worse when allocating memory in the kernel, because you can generally write anywhere, whether it is YOUR memory or not - since all kernel memory is mapped under one mapping, rather than individual user-mode mappings. So overwriting a buffer in kernel mode can cause the screen to go beserk, or it may cause a disk-block to be written with the wrong data, or crash the disk-driver because a pointer to the next block to be written is now invalid, etc, etc.]



    Now for Azazel's question:
    You use & when you want the address of the input to scanf. Since C automatically translates arrays into the address of the first element, you don't need (and shouldn't use) & for char arrays. You also, obviously, shouldn't use & if you pass a pointer to scanf - becasue that would take the address of the pointer, and that's not the right thing to do.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    Sep 2007
    Posts
    9
    Quote Originally Posted by lilcoder View Post
    Okay let's take a look at this wrong scanf-implementation:
    Code:
    #include <stdio.h>
    
    int main(void) {
         
           char *buff[20];
    
           scanf("&#37;s",buff);
           printf("%s\n",buff);
     
           return 0;
    }
    If I take now a large enough input to write over the basepointer or even eip , I'm getting a segfault. The correct usage would be of course scanf("%20s",buff);.

    But now take a look at this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void) {
         
           char *buff;
    
           buff = malloc(20);
           scanf("%s",buff);
      
           printf("%s\n",buff);
           
           return 0;
    }
    No matter how large the input was it never crashed in my tests but read everything and printed everything out again. Just if I free the memory after the printf-instruction again with free(buff); I'm crashing:
    Code:
    *** glibc detected *** ./hello: free(): invalid next size (fast): 0x0804a008 ***
    ======= Backtrace: =========
    /lib/tls/i686/cmov/libc.so.6[0xb7e167cd]
    /lib/tls/i686/cmov/libc.so.6(cfree+0x90)[0xb7e19e30]
    ./hello[0x804845d]
    /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xdc)[0xb7dc4ebc]
    ./hello[0x8048391]
    ======= Memory map: ========
    08048000-08049000 r-xp 00000000 fe:00 1661139    /home/user/Desktop/hello
    08049000-0804a000 rw-p 00000000 fe:00 1661139    /home/user/Desktop/hello
    0804a000-0806b000 rw-p 0804a000 00:00 0          [heap]
    b7c00000-b7c21000 rw-p b7c00000 00:00 0 
    b7c21000-b7d00000 ---p b7c21000 00:00 0 
    b7dae000-b7daf000 rw-p b7dae000 00:00 0 
    b7daf000-b7eea000 r-xp 00000000 08:05 456891     /lib/tls/i686/cmov/libc-2.5.so
    b7eea000-b7eeb000 r--p 0013b000 08:05 456891     /lib/tls/i686/cmov/libc-2.5.so
    b7eeb000-b7eed000 rw-p 0013c000 08:05 456891     /lib/tls/i686/cmov/libc-2.5.so
    b7eed000-b7ef0000 rw-p b7eed000 00:00 0 
    b7ef5000-b7f00000 r-xp 00000000 08:05 423552     /lib/libgcc_s.so.1
    b7f00000-b7f01000 rw-p 0000a000 08:05 423552     /lib/libgcc_s.so.1
    b7f01000-b7f05000 rw-p b7f01000 00:00 0 
    b7f05000-b7f1e000 r-xp 00000000 08:05 423511     /lib/ld-2.5.so
    b7f1e000-b7f20000 rw-p 00019000 08:05 423511     /lib/ld-2.5.so
    bfc09000-bfc1e000 rw-p bfc09000 00:00 0          [stack]
    ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
    Aborted
    How much space will actually be there on the heap until something serious happens? Why is it crashing when freed?
    dear, in both version of program, u are allocating different amount of memory to 'buf', in firts version static memory of 80 bytes is being allocated while in second one it's only 20 bytes....*buf[20]......... is an array of charcter pointers...................keep it in mind..............such type of programming practise as in version 1 is really dangerous........
    whatever u have done in version 1 that is not acceptable.........
    Last edited by PrashantVaidwan; 09-29-2007 at 05:02 AM.

  6. #6
    Registered User
    Join Date
    Sep 2007
    Posts
    26
    @matsp: thx for explaining!

    @PrashantVaidwan: hmm I thought I would make just one pointer to a buffer of 20bytes with this...thanks for making this clear

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Lame null append cause buffer to crash
    By cmoo in forum C Programming
    Replies: 8
    Last Post: 12-29-2008, 03:27 AM
  2. Hooking Crash?
    By Elysia in forum Windows Programming
    Replies: 9
    Last Post: 03-15-2008, 01:13 PM
  3. Can not debug a crash
    By hannibar in forum Windows Programming
    Replies: 2
    Last Post: 06-30-2007, 10:02 AM
  4. Dynamic array sizing causes crash
    By Mithoric in forum C++ Programming
    Replies: 3
    Last Post: 12-30-2003, 07:46 AM
  5. FYI: asctime(gmtime(&mytime)) = crash!
    By anonytmouse in forum C Programming
    Replies: 2
    Last Post: 09-29-2003, 02:24 AM