I have a string function that takes a pointer to the source string and returns a pointer to the destination string. This feature is currently working, but I worry that I am not following the best practices governing malloc, realloc and free.
What differs from my function is that the length of the destination line does not match the original line, so realloc () needs to be called inside my function. I know, looking at the documents ...
http://www.cplusplus.com/reference/cstdlib/realloc/
that the memory address may change after realloc. This means that I cannot "pass by reference", as a C programmer for other functions, I need to return a new pointer.
So, the prototype of my function:
//decode a uri encoded string char *net_uri_to_text(char *);
I don’t like the way I do it, because I have to free the pointer after the function starts:
char * chr_output = net_uri_to_text("testing123%5a%5b%5cabc"); printf("%s\n", chr_output); //testing123Z[\abc free(chr_output);
This means that malloc () and realloc () are called inside my function, and the free () function is called outside my function.
I have a background in high-level languages (perl, plpgsql, bash), so my instinct is the proper encapsulation of such things, but this may not be the best practice in C.
Question: Is my method the best practice, or is there a better way I should follow?
full example
Compiles and runs with two warnings about unused arguments argc and argv, you can safely ignore these two warnings.
example.c:
#include <stdio.h> #include <string.h> #include <stdlib.h> char *net_uri_to_text(char *); int main(int argc, char ** argv) { char * chr_input = "testing123%5a%5b%5cabc"; char * chr_output = net_uri_to_text(chr_input); printf("%s\n", chr_output); free(chr_output); return 0; } //decodes uri-encoded string //send pointer to source string //return pointer to destination string //WARNING!! YOU MUST USE free(chr_result) AFTER YOU'RE DONE WITH IT OR YOU WILL GET A MEMORY LEAK! char *net_uri_to_text(char * chr_input) { //define variables int int_length = strlen(chr_input); int int_new_length = int_length; char * chr_output = malloc(int_length); char * chr_output_working = chr_output; char * chr_input_working = chr_input; int int_output_working = 0; unsigned int uint_hex_working; //while not a null byte while(*chr_input_working != '\0') { //if % if (*chr_input_working == *"%") { //then put correct char in sscanf(chr_input_working + 1, "%02x", &uint_hex_working); *chr_output_working = (char)uint_hex_working; //printf("special char:%c, %c, %d<\n", *chr_output_working, (char)uint_hex_working, uint_hex_working); //realloc chr_input_working++; chr_input_working++; int_new_length -= 2; chr_output = realloc(chr_output, int_new_length); //output working must be the new pointer plys how many chars we've done chr_output_working = chr_output + int_output_working; } else { //put char in *chr_output_working = *chr_input_working; } //increment pointers and number of chars in output working chr_input_working++; chr_output_working++; int_output_working++; } //last null byte *chr_output_working = '\0'; return chr_output; }