0
int length = 12;
char *filename;
char *key;

filename = (char *)calloc(length, sizeof(char));
strcpy(filename, "Hello World");//filename = "Hello World\0";

Now I want to trim 5 chars from left

key = filename + 6;
*(filename + 5) = 0;

free(filename);

printf("%s\n", key);
printf("%s\n", filename); //No Segmentation Fault Why??

I can achieve this using memcpy or strcpy but can I do this the above way?

botchedDevil
  • 260
  • 1
  • 4
  • 14
  • 3
    `filename = "Hello World\0";` leaks the memory allocated on the line above. `*(filename +5) = 0;` is then undefined behaviour, as is `free(filename);`. – Daniel Fischer Jun 22 '13 at 14:25
  • That’s not guaranteed to break, but it’s broken. Anyways,`free` isn’t null-terminated. Setting `*(filename + 5)` to 0 doesn’t stop it from freeing the rest of the string. – Ry- Jun 22 '13 at 14:28
  • If I interpret the title of the question correctly, what you want is to `free` only a part of some allocated memory, retaining the rest? That is not possible. Well, _some_ implementation might give you the hooks into the memory allocation functionality that could make it possible, but that's theory. There is no remotely portable way. – Daniel Fischer Jun 22 '13 at 14:32
  • I am sorry I am pretty new to pointers. ok may be the code is not ok, but my idea is to free the starting chars. Will that work? How does free know the length of memory to free? – botchedDevil Jun 22 '13 at 14:36
  • 1
    @botchedDevil No, it will not work. If you know exactly how the malloc machinery works in your implementation, you _might_ be able to hack something to "make it work", but even if it's possible at all, it's a bad idea 99.999% of the time. – Daniel Fischer Jun 22 '13 at 14:50
  • 1
    @botchedDevil "How does free know the length of memory to free?" That's an excellent question! Here is [a good answer](http://stackoverflow.com/questions/1518711/c-programming-how-does-free-know-how-much-to-free) (hint: `malloc`/`calloc` leaves a little hint for it). – Sergey Kalinichenko Jun 22 '13 at 14:53
  • @DanielFischer could you make that an answer! – botchedDevil Jun 22 '13 at 15:26
  • @botchedDevil If it must be. But at the moment, I'm rather too lazy. Perhaps you can persuade dasblinkenlight to include what you need into his/her answer? – Daniel Fischer Jun 22 '13 at 15:30
  • @dasblinkenlight please do the honours. Thanks! – botchedDevil Jun 22 '13 at 16:51

2 Answers2

4

This is just wrong:

// So far so good...
filename = (char *)calloc(length, sizeof(char));
// No!!! You just leaked the previously allocated memory block!
// The `\0` at the end is also wrong.
filename = "Hello World\0";
// This is OK
key = filename + 6;
// You are writing into memory of a string literal, that's undefined behavior
*(filename + 5) = 0;
// You are freeing a string literal, that's undefined behavior too
free(filename);

As for no segfault part, undefined behavior may not manifest itself right away: for example, when you free a wrong region, the freeing itself may work, but a subsequent allocation could fail.

If you would like to shorten the string, make a copy, and free the original:

char *filename = malloc(length);    // no cast
strcpy(filename, "Hello, world");   // no \0
char *trimmed = strdup(filename+6); // Make a copy
free(filename);                     // Free the original
filename = trimmed;                 // You are done!

In general, you can free only what you have allocated. The main reason for this is that malloc/calloc/realloc store "bookkeeping" information in the memory associated with the address returned to you, often in a block immediately prior to the allocated address. You can try faking it, but even if it works, the solution would be fragile and non-portable.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • "No!!! You just leaked the previously allocated memory block!" I understand this but when I point to a string literal inside a function it mean i am pointing at a memory block inside the loaded function, thus my pointer will be good as long as the function is loaded in the memory (though function unload wont happen during the execution of a program). So am I thinking in the right direction here? – botchedDevil Jun 23 '13 at 03:00
  • @botchedDevil The problem with the first assignment is not what's being assigned, but what's being overwritten by the assignment. You are not copying the string into the allocated space, you are replacing the pointers. The new pointer is OK, but the old pointer in the `filename` is now gone. You can no longer call `free` on it, which means that there is a memory leak. – Sergey Kalinichenko Jun 23 '13 at 10:29
0

Even when you clean up the memory lead problem by using strcpy() or strncpy() to initialize your filename to "Hello World", you will still get a seg fault on your last line because you're freeing the heap memory previously allocated for filename 2 lines above. Move your free() to the end and you'll be relatively fine.

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

int main(int argc, char** argv)
{
    int length = 12;
    char *filename;
    char *key;

    filename = (char *)calloc(length, sizeof(char));
    strcpy(filename, "Hello World");
    key = filename + 6;
    *(filename + 5) = 0;

    printf("%s\n, key");
    printf("%s\n", filename); //No Segmentation Fault Why??

    free(filename);
}
alpartis
  • 1,086
  • 14
  • 29
  • Well, using `free`d memory is undefined behaviour, it need not segfault, it's perfectly valid for it to pretend to work (except on Tuesdays). – Daniel Fischer Jun 22 '13 at 14:52