helloworld
helloworld

Reputation: 21

How can I free memory and at the same time return a pointer?

I have these functions

char *hash(char *stringa, char *tipohash) {
    if (strcmp(tipohash, "md5") == 0) {
        stringa = md5(stringa);
    }
    return stringa;
}

char *md5(char *stringa) {
    unsigned char risultato[MD5_DIGEST_LENGTH];
    int i;
    char *hashfinale = malloc(sizeof(char) * MD5_DIGEST_LENGTH * 2);
    MD5((const unsigned char *)stringa, strlen(stringa), risultato);
    for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
        sprintf(hashfinale + 2 * i, "%02x", risultato[i]);
    }
    return (char *)hashfinale;
}

How I can return (char *)hashfinale doing the free without losing the value of the string?

This is the caller

char *hashlinea = hash(stringa, hashType);

Upvotes: 2

Views: 205

Answers (3)

chqrlie
chqrlie

Reputation: 144695

There is a problem in your md5 function: the size allocated for the MD5 hash must be one byte longer for the null terminator:

char *hashfinale = malloc(sizeof(char) * (MD5_DIGEST_LENGTH * 2 + 1));

Note that in C (and C++) sizeof(char) is 1 by definition, so you could just write:

char *hashfinale = malloc(MD5_DIGEST_LENGTH * 2 + 1);

Regarding your question, hash returns either its argument or an allocated object. This is a problem for memory management, as yo may not know later in the program if the return value must be freed or not. Passing the destination array for the hash string is a better alternative, otherwise you should duplicate the string so the return value of hash can be unconditionally freed:

char *md5(const char *stringa) {
    unsigned char risultato[MD5_DIGEST_LENGTH];
    int i;
    char *hashfinale = malloc(MD5_DIGEST_LENGTH * 2 + 1);
    MD5((const unsigned char *)stringa, strlen(stringa), risultato);
    for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
        sprintf(hashfinale + 2 * i, "%02x", risultato[i]);
    }
    return hashfinale;
}

// always free the return value
char *hash(const char *stringa, const char *tipohash) {
    if (!strcmp(tipohash, "md5")) {
        return md5(stringa);
    } else {
        return strdup(stringa);
    }
}

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409166

There are basically two ways to solve the problem, and none of them involves your code calling free.


The first way is to just do nothing different from now, except to add documentation so the user of your hash function knows that the code must call free on the returned pointer:

// This is the code using your function
char *hashlinea = hash(stringa,hashType);

// Some code using hashlinea

free(hashlinea);

The second way is to pass a pointer to an existing array, and your code use that array instead of allocating it using malloc:

char hashlinea[MD5_DIGEST_LENGTH*2];
hash(stringa, hashType, hashlinea);

For this your hash function needs to pass on the third argument to the md5 function, which should use it instead of allocating memory:

char *md5(char *stringa, char *hashfinale){
    unsigned char risultato[MD5_DIGEST_LENGTH];
    int i;
    // No memory allocation here
    MD5((const unsigned char *)stringa, strlen(stringa), risultato);
    for(i = 0; i < MD5_DIGEST_LENGTH; i++) {
        sprintf(hashfinale + 2*i,"%02x",risultato[i]);
    }
    return hashfinale;
}

Upvotes: 2

0___________
0___________

Reputation: 67476

It is not possible. IMO it is better to pass the pointer to the buffer. The caller will be responsible for the memory management

char *md5(char *stringa, char *hashfinale){
 ...
}

Upvotes: 1

Related Questions