2

I'm a self enthusiast CS learner. (please take my comments as a geek's query for further clarification he needed) I was writing a simple c script to get a better understanding on dynamically allocated memory (aside from queue and stack). To do so I've created a simple "malloced" pointer to the "n int type heap memory."
int *array;
    int size = 10;
    //point to a chunk of 10 (m)allocated memory in heap (?) am I right ? 
    array = (int *) malloc(sizeof(int) * size);

Now I have done some operation on them. for example

//passing array as reference (?)

void handy_array(int *pointer, int size) {

    /*operation on the (m)allocated array of given size created in heap*/

    for(int i = 0; i < size; i++) {
        pointer[i] = i-10 ;
    }
    return;
}

So far so good, now we can use this array[size] like a char string[n] = "a string." But when freeing the memory using this method

void free_array(int *array, int size) {

    for(int i= 0; i < size; i++){
        //free the ith assigned address and its value in heap memory
        free(&array[i]);

    }
    return;
}

Now, I'm getting this interesting error message-

    *** Error in `./main': free(): invalid pointer: 0x0973d00c ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x67377)[0xb75f6377]
/lib/i386-linux-gnu/libc.so.6(+0x6d2f7)[0xb75fc2f7]
/lib/i386-linux-gnu/libc.so.6(+0x6dbb1)[0xb75fcbb1]
./main[0x8048590]
./main[0x80484c8]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf7)[0xb75a7637]
./main[0x8048391]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:01 22937845   /directory/to/the/script
08049000-0804a000 r--p 00000000 08:01 22937845   /directory/to/the/script
0804a000-0804b000 rw-p 00001000 08:01 22937845   /directory/to/the/script
0973d000-0975e000 rw-p 00000000 00:00 0          [heap]
b7400000-b7421000 rw-p 00000000 00:00 0 
b7421000-b7500000 ---p 00000000 00:00 0 
b7559000-b7575000 r-xp 00000000 08:01 13239646   /lib/i386-linux-gnu/libgcc_s.so.1
b7575000-b7576000 rw-p 0001b000 08:01 13239646   /lib/i386-linux-gnu/libgcc_s.so.1
b758f000-b773e000 r-xp 00000000 08:01 13239459   /lib/i386-linux-gnu/libc-2.23.so
b773e000-b773f000 ---p 001af000 08:01 13239459   /lib/i386-linux-gnu/libc-2.23.so
b773f000-b7741000 r--p 001af000 08:01 13239459   /lib/i386-linux-gnu/libc-2.23.so
b7741000-b7742000 rw-p 001b1000 08:01 13239459   /lib/i386-linux-gnu/libc-2.23.so
b7742000-b7745000 rw-p 00000000 00:00 0 
b775d000-b7760000 rw-p 00000000 00:00 0 
b7760000-b7762000 r--p 00000000 00:00 0          [vvar]
b7762000-b7763000 r-xp 00000000 00:00 0          [vdso]
b7763000-b7785000 r-xp 00000000 08:01 13239455   /lib/i386-linux-gnu/ld-2.23.so
b7785000-b7786000 rw-p 00000000 00:00 0 
b7786000-b7787000 r--p 00022000 08:01 13239455   /lib/i386-linux-gnu/ld-2.23.so
b7787000-b7788000 rw-p 00023000 08:01 13239455   /lib/i386-linux-gnu/ld-2.23.so
bf7eb000-bf80c000 rw-p 00000000 00:00 0          [stack]
Aborted (core dumped)

My precise questions are:
0. which is the practical practice to allocate memory chunk- either from global or local scope, or initiating them from main method and work on local methods that I'm doing here.
1. What is the exact method to free memory in the aforementioned scenario ?
and
(optional; and if you think irrelevant please ignore)
2. I want some hints to understand the interesting error message like backtrace and memory map
Thanks in advance

ph03n1x
  • 25
  • 5

1 Answers1

2

Firstly, you need not cast the return value of malloc() in the following statement:

array = (int *) malloc(sizeof(int) * size);
//instead use:
array = malloc(sizeof(*array) * size); 
//this is fine and here `*array` instead of `int` to denote the type

Here's why: https://stackoverflow.com/a/605858/5281962


coming to your problem, you need to free your malloced pointer only once but instead you are doing it more than once by using a free() in a for loop in your free_array() function

for(int i= 0; i < size; i++){
    //free the ith assigned address and its value in heap memory
    free(&array[i]);
}

instead of the loop just do:

free(array); //done!
Community
  • 1
  • 1
Cherubim
  • 5,287
  • 3
  • 20
  • 37
  • 1
    So, the cupboard is no longer your cupboard and its content is now undefined. It just hasn't yet been recycled. – Weather Vane Nov 08 '16 at 16:50
  • @ph03n1x have a look at this: http://stackoverflow.com/documentation/c/4726/memory-management/3631/freeing-memory#t=201611081654295531306 – Cherubim Nov 08 '16 at 16:56
  • 2
    As I said, the content of the cupboard has not yet been replaced, but when it is you will come unstuck. Why did you `free` the memory when you still want to access it? I don't understand you... suppose you rent a car, and then return it to the rental company. When you leave, do you say "Hey! That car is still there, I could keep using it?" – Weather Vane Nov 08 '16 at 17:00
  • yes @ph03n1x I know it might be confusing but, that's completely undefined behaviour.. nobody can expect the unexpected! right :) Just make sure that you never access freed memory as you never expect what a freed pointer points to – Cherubim Nov 08 '16 at 17:03
  • 1
    @ph03n1x When you free memory, you're simply telling the OS you don't want it anymore. For most applications (security excepted) it would be a waste of cycles to "clear" the memory (what would that even do? a bunch of 0s or Fs can certainly be valid data too). You might still be able to read your data after a `free`, but you can't count on that since you don't own it anymore. The OS is free to come scoop it up. Same concept when you delete a file off your hard drive. The OS doesn't actually erase it. Those sectors are just marked as free to be overwritten. – yano Nov 08 '16 at 17:04
  • 1
    @ph03n1x This is tagged as `c++` and is talking about variable scope, but the concepts are the same: http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794 – yano Nov 08 '16 at 17:11