5

If I have allocated a memory chunk say

char *a =(char*)malloc(sizeof(char)*10);   

and I do

strcpy( "string of len 5",a);   

then is there a way to free the left over part of my memory chunk?
In other scenario if I do

strcpy("string of len5", (a+5));

then first half will be empty. is there a way to free() that first part without deallocating the second half?

Please don't suggest realloc() as it allocates a new chunk of memory copy content there and release the previous.(AKAIK).

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
VikasPushkar
  • 392
  • 3
  • 18
  • 5
    "Please don't suggest `realloc()`" – it's exactly `realloc()` that you should use. – The Paramagnetic Croissant Jul 23 '15 at 10:40
  • Got any problem with `realloc()` ? – ameyCU Jul 23 '15 at 10:42
  • 2
    If the reason for "don't suggest `realloc`" is because there are multiple aliased copies of that pointer floating around which would potentially be invalidated by a call to realloc - well, don't keep multiple aliased copies of pointers laying around. Programming requires discipline. Best of luck. – Bob Jarvis - Слава Україні Jul 23 '15 at 11:07
  • 2
    BTW `sizeof(char)` is redundant, it is guaranteed to be 1 by the standard. – user4520 Jul 23 '15 at 11:17
  • 1
    and in C you [don't cast the result of `malloc`](http://stackoverflow.com/q/605845/995714) – phuclv Jul 23 '15 at 11:42
  • ^^^ what @BobJarvis says. Even if you could deallocate half the space without realloc, the other pointer aliases would not know about it and so any other functions/threads operating with the aliased pointers would likely UB themselves to death. Try very hard to not design bad code/data. – Martin James Jul 23 '15 at 12:23

6 Answers6

7

No, there is no way you can free() half or part of the dynamically allocated memory. You need to free() it all at a time.

While getting the memory through dynamic memory allocation, you basically get a pointer. You need to pass the exact pointer to free(). Passing a pointer to free() which is not returned by malloc() or family, is undefined behaviour.

FYI, see this related answer.

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
4

realloc() isn't required to copy and a good implementation avoids unnecessary copies. You should really rely on that. (to clarify: for performance reasons, of course. Always assume an implementation may take a copy)

#include <stdlib.h>
#include <stdio.h>

int main()
{
    void *test1 = malloc(16);
    void *test2 = realloc(test1, 8);
    free(test2);

    printf("malloc: %x -- realloc: %x\n", test1, test2);
    return 0;
}

example output:

malloc: 4779c0 -- realloc: 4779c0

2

The malloc(3) API doesn't allow this, other than with realloc(3). In common implementations, shrinking with realloc (usually?) won't trigger a copy, and esp. not if the buffer was large.

If you really want to be able to guarantee non-copying, implement your own allocator on top of POSIX mmap(2) / munmap(2). You can unmap part of a mapping without affecting the pages that weren't in the address range given.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
1

Without using realloc it is impossible to do the task in the frames of the C Standard. There is nothing complicated in using realloc.

Here is a demonstrative program that shows how it can be done

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

#define HELLO_WORLD "Hello World"

int main( void )
{
    char *s;
    size_t n = sizeof( HELLO_WORLD );

    s = malloc( n );

    strcpy( s, HELLO_WORLD );

    puts( s );

    memmove( s, s + 6, n - 6 ); 

    puts( s );

    char *t = realloc( s, n - 6 );

    if ( t ) s = t;

    puts( s );

    free( s );
}

The program output is

Hello World
World
World

Another approach is to copy simply the substring in another allocated string. For example

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

#define HELLO_WORLD "Hello World"

int main( void )
{
    char *s;
    size_t n = sizeof( HELLO_WORLD );

    s = malloc( n );

    strcpy( s, HELLO_WORLD );

    puts( s );

    do
    {
        char *t = malloc( n - 6 );

        if ( t )
        {
            strcpy( t, s + 6 );
            free( s );
            s = t;
        }
    } while( 0 );        

    puts( s );

    free( s );
}

The program output is

Hello World
World
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

there is no way for you to do this, and is there any necessary to free half? it is not safe at all. Dynamically allocated memory must be free all.

wangli_64604
  • 103
  • 5
-1

Call to malloc when succeed in returning a logically contiguous block of memory from your program's HEAP memory space just bit more than what you requested.

This extra memory which is used to store information such as the size of the allocated block, and a link to the next free/used block in a chain of blocks.

When you free your pointer, it uses that address to find the special information it added to the beginning (usually) of your allocated block.

So therefore you can't free memory less than what you allocated using malloc.If you pass different address it will give undefined behaviour.

For this purpose realloc is used .

ameyCU
  • 16,489
  • 2
  • 26
  • 41