Tam Lam
Tam Lam

Reputation: 135

When to use malloc in function?

I am learning the basic of C programming and find it quite strange and difficult. Especially with dynamic memory allocation, pointer and similar things. I came upon this function and don't quite understand what is wrong with it.

 char *strdup(const char *p)
    {
      char *q;
       strcpy(q, p);
       return q;
    }

I think I have to malloc and free q. But the function " return q". Doesn't that mean that it will store q value in its own memory. So the data still be saved after the function executed?

When it is appropriate to use malloc? As I understand so far is that I have to malloc a new variable every time I need that variable declared in a function to be used elsewhere. Is that true? Is there any other situation where malloc is needed?

Upvotes: 0

Views: 1478

Answers (4)

someone_ smiley
someone_ smiley

Reputation: 1066

I think I have to malloc and free q. But the function " return q". Doesn't that mean that it will store q value in its own memory. So the data still be saved after the function executed?

No, your data won't be saved. In fact your pointer q is being used without allocating it's size can cause problems. Also, once this function execution complete, variable char* q will be destroyed.

You need to allocate memory to pointer q before copying data as suggested by @Michael's answer.But once you finish using the data return by this function, you will need to manually free() the memory you allocated or else it will cause memory leak (a situation where the memory is allocated but there is no pointer refer to that chunk of memory you allocated and hence will be inaccessible throughout program execution)

char *strdup(const char *p) // From @Michael's answer
{
   char *q;
   q = malloc(strlen(p) + 1);
   if(NULL != q)
       strcpy(q, p);
   return q;
}

void someFunction()
{
    char* aDupString = strdup("Hello World!!!");
    /*... somecode use aDupString */
    free(aDupString); // If not freed, will cause memory leaks
}

When it is appropriate to use malloc? Is there any other situation where malloc is needed?

It is appropriate to use in following situations:

1> The usage size of array are unknown at compile time.

2> You need size flexibility. For example, your function need to work with small data size and large data size. (like Data structure such as Link list,Stacks, Queues, etc.)

As I understand so far is that I have to malloc a new variable every time I need that variable declared in a function to be used elsewhere. Is that true?

I think this one is partially true. depending on what you are trying to achive, there might be a way to get around using malloc though. For example, your strdup can also be rewrite in following way:

void strdup2(const char *p, char* strOut) 
{
    // malloc not require
    strcpy(strOut, p);
}

void someFunction()
{
    char aString[15] = "Hello World!!!";
    char aDupStr[sizeof(aString)];
    strdup2(aString, aDupStr);

    // free() memory not required. but size is not dynamic.
}

Upvotes: 0

babon
babon

Reputation: 3774

malloc(X) creates space (of size X bytes) on the heap for you to play with. The data that you write to these X byes stays put when your function returns, as a result, you can read what your strdup() function wrote to that space on the heap.

free() is used for freeing space on the heap. You can pass a pointer to this function that you obtained only as a result of a malloc() or realloc() call. This function may not clear out the data, it just means that a subsequent call to malloc() may return the address of the same space that you just freed. I say "may" because these are all implementaion defined and should not be relied upon.

In the piece of code you wrote, the strcpy() function copies the bytes one by one from p to q until it finds a \0 at the location pointed to by q (and then it copies the \0 as well). In order to write data somewhere, you need to allocate space first for the data to be written, hence, one option is that you call malloc() to create some space and then write data there.

Well, calling free() is not mandatory as your OS will reclaim the space allocated by malloc() when you program ends, but as long as your program runs, you may be ocupying more space than you need to - and that's bad for your program, for other programs, for the OS and the universe as a whole.

Upvotes: 0

argoc
argoc

Reputation: 333

The type of q is a pointer, and pointers hold addresses -- so what you are returning is the address that pointer holds.

Until you give that pointer a valid address, it points off to who-knows-where, memory that you may or may not own and have the right to access. So, the strdup call will copy a string from the address held in p into some location you probably don't own.

If you had done a malloc first, and given q the results of the malloc, then q would hold a valid address, and your strdup would put the copy into memory that you did own (assuming you malloc'd enough space for the string -- a strlen on p would tell you how much you needed).

Then, when you returned q, you would be giving the caller the address as well. Any code with that address can see the string you put there. If some future code were to free that address, then what it holds is up in the air -- it could be anything at all.

So, you don't want to free q before you return the address that it holds -- you need to let the caller free the address it gets from you, when it is ready to do so.

In terms of when you malloc, yes, if you want to return an address that will remain viable after your function completes, you need to malloc it -- giving the caller the address of a local variable, for example, would be bad: the memory is freed when the function returns, you don't own it anymore.

Another typical use of malloc is for building up dynamic data structures like trees and lists -- you can't know how much memory you need up front, so you build the list or tree up as you need to, malloc'ing more memory for each node in the structure.

Upvotes: 5

GMichael
GMichael

Reputation: 2776

My personal rules are: use malloc() when an object is too big to put on the stack or/and when it has to live outside the scope of the current block. In your case, I believe, you should do something like the following:

char *strdup(const char *p)
{
   char *q;
   q = malloc(strlen(p) + 1);
   if(NULL != q)
       strcpy(q, p);
   return q;
}

Upvotes: 4

Related Questions