1

I have the following function:

char * decrypt(const char *p, int key) {
  char *tmp = malloc(strlen(p) + 1);
  for (int i = 0; p[i] != '\0'; i++) {
    if (p[i] >= 'A' && p[i] <= 'Z') {
      if (key <= p[i] - 'A')
        tmp[i] = p[i] - key;
      else
        tmp[i] = p[i] - key + 'Z' - 'A' + 1;
    } else if (p[i] >= 'a' && p[i] <= 'z') {
      if (key <= p[i] - 'a')
        tmp[i] = p[i] - key;
      else
        tmp[i] = p[i] - key + 'Z' - 'A' + 1;
    }
  }
  return tmp;
}

I'm allocating memory for the temporary pointer *temp with:

char *tmp = malloc(strlen(p) + 1);

but I'm not freeing it anywhere.

As far as I know, there are 4 options for freeing that memory:

  1. Use free() in the same scope (which is not possible for me, because I must return the pointer)
  2. Use alloca() which is not supported by every compiler (not ANSI C)
  3. malloc() the pointer outside the function and pass that pointer to the function, then free() it outside the function
  4. assign the returned pointer to a variable and free that variable

This is the code for option #4:

char *var;
var = malloc(MAX);
var = decrypt("Hello", 1);
free(var);

Do I have to malloc() the variable var when I assign it a returned pointer, because that pointer is already malloc()ed?

My questions are:

What is the best way of using malloc() inside a function?

If I go for the 4th option, do I have to malloc() the variable before assigning it the returned pointer?

fenceop
  • 1,439
  • 3
  • 18
  • 29

4 Answers4

3

It should be:

char *var = decrypt(whatever);
// ...use var...
free(var);

I don't know why you want to leak some memory beforehand with your code example.

Your plan (3) of allocating memory beforehand and having the function fill it in is also viable, but it makes for more verbose code because it introduces the possibility of the function causing a buffer overflow.

alloca wouldn't work because that space is deallocated when the function returns.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • plan 3 is good because you can choose if it should be allocated on the stack or heap - function is more flexible. – Konrad Jul 26 '19 at 18:20
  • also, it's not very obvious that you should free the returned pointer - it's easy to forget. Other answer mentioned that it's good to append some suffix like _ma – Konrad Jul 26 '19 at 18:21
  • in win api option 3 is very common e.g. https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersinfo – Konrad Jul 26 '19 at 18:21
  • `_CrtDumpMemoryLeaks` is very helpful :) https://learn.microsoft.com/en-us/visualstudio/debugger/finding-memory-leaks-using-the-crt-library?view=vs-2019 and https://stackoverflow.com/questions/2153776/how-to-use-crtdumpmemoryleaks – Konrad Jul 26 '19 at 18:26
  • But will the memory allocated for ``tmp`` inside the function (``char *tmp = malloc(strlen(p) + 1);``) be freed as well? – Tropilio Oct 21 '19 at 14:42
  • 1
    @FrancescoBoccardo `free(var)` frees that memory, since the function does `return tmp;` – M.M Oct 22 '19 at 00:44
  • @M.M sorry for the necromancy, but your comment about mem leaking is because he preallocated MAX mem and might not need that much right? i didnt see a mem issue anywhere else. please advise - it is important to know bad practice cases. – mindoverflow May 22 '23 at 01:17
  • or it is just that they didnt use stack space and then malloc a pointer and set the val right before return? – mindoverflow May 22 '23 at 01:23
  • 1
    @mindoverflow the space allocated by `malloc(MAX);` is never freed. The very next line sets `var` to point to a different block of memory. – M.M May 23 '23 at 02:36
  • @M.M oh wow. i knew this but still missed it. c is a minefield! thanks – mindoverflow May 25 '23 at 00:51
2

You can modify the signature of the decrypt function so that it provides the pointer where the function writes the result.

void decrypt(char* dest, const char *p, int key);

This way, it is the full responsibility of the caller to manage this memory space.

Tropilio
  • 1,395
  • 1
  • 9
  • 27
Tristan
  • 126
  • 1
  • 5
0

Q: Which is the best way of using malloc() inside a function?

A: If you really want to allocate memory inside the function (as it is now) you must free memory outside this function (perhaps with other complementary function). Sometimes people use special names for such functions (e.g. decrypt_ma() instead of decrypt()) to remember about the fact of memory allocation.

Q: If I would use the 4th way, would I have to malloc() that variable before assinging it the returned pointer?

A: If you allocate memory before calling the decrypt(), decrypt() should not return pointer at all (you will do all manipulation with p that should be not const in the body of the function).

VolAnd
  • 6,367
  • 3
  • 25
  • 43
0

A simple alternative is to modify the string in place:

void decrypt(char *p, int key) {
    for (; *p; p++) {
        if (*p >= 'A' && *p <= 'Z') {
            if (key <= *p - 'A')
                *p -= key;
            else
                *p += ('Z' - 'A' + 1) - key;
        } else
        if (*p >= 'a' && *p <= 'z') {
            if (key <= *p - 'a')
                *p -= key;
            else
                *p += ('Z' - 'A' + 1) - key;
        }
    }
}

Note that you can write a much simpler and more efficient implementation with a 256 byte array.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • But when I edit the pointer inside the array, wouldn't it be also edited outside the the array, because im working with the adress of the char array? –  Feb 22 '15 at 21:41