This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getinfo(unsigned int a, unsigned int b, char **pStr);
int main(){
unsigned int len_max = 8;
unsigned int current_size = 0;
current_size = len_max;
char *host, *user;
char *pStr = malloc(len_max);
if(pStr == NULL){
perror("\nMemory allocation\n");
return EXIT_FAILURE;
}
printf("Inserisci hostname: ");
getinfo(len_max, current_size, &pStr);
if((host=malloc(strlen(pStr)+1 * sizeof(char))) == NULL) abort();
strncpy(host, pStr, strlen(pStr)+1);
printf("Inserisci username: ");
getinfo(len_max, current_size, &pStr);
if((user=malloc(strlen(pStr)+1 * sizeof(char))) == NULL) abort();
strncpy(user, pStr, strlen(pStr)+1);
printf("\nHostname: %s\nUsername: %s\n", host, user);
free(pStr);
free(host);
free(user);
return EXIT_SUCCESS;
}
void getinfo(unsigned int a, unsigned int b, char **pStr){
unsigned int i = 0;
int c = EOF;
while((c = getchar()) != '\n'){
(*pStr)[i++] = (char)c;
if(i == b){
b = i+a;
if((*pStr = realloc(*pStr, b)) == NULL){
perror("\nMemory allocation error\n");
exit(EXIT_FAILURE);
}
}
}
(*pStr)[i]='\0';
}
The problem is that if realloc fails i have to exit (because i cannot allocate memory). But before exit there’s to free all the used pointers.
The problem is that if the function fails the first time there’s only 1 pointer that have to be freed (pStr).
But if it fails the second time there’s 2 pointers that have to be freed (pstr & user).
How can i fix it?
As already noted, if you are going to exit, then all practical modern O/S will release the allocated memory before exit. It was not always thus; early versions of AmigaDOS, IIRC, did not reclaim allocated memory automatically until reboot.
This is a simple case. There are more complex cases, such as you are parsing a file into memory and the 579th memory allocation fails, and you’d like to release the previous 578 memory allocations so that the user can try again.
In such cases, you have to keep a record of each memory allocation that is relevant (which may itself require some memory allocation — though if you’re parsing a file, you probably have a master structure which contains the complete description) and then release all the allocated data.
In your example, if this was not a
main()function and if you did not abort on memory allocation error, then you would need to ensure that the three allocated pointers are released on exit from the function. The standard tricks for that include:Initialize the pointers to 0 so they can be freed reliably:
When using
realloc(), do not assign the result to the expression passed as the first parameter:Do NOT do:
If (when)
ptris the only reference to the allocated memory and the reallocation fails, you’ve just leaked memory; there is no way to release the memory that is still allocated to you.Use:
The trouble with the simpler version is that you’ve just thrown away the only reference to the allocated memory. (Note that your code falls into the dangerous/leaking pattern).
Note that pretty much every function that acquires resources must either release the acquired resource before returning, or make the resource available to some other part of the program so that the other part can release the resource when it is done with it.
The ‘make available’ operation might be returning the acquired resource (think of it as memory, but it could be a file descriptor, directory stream, or any of a large number of other allocated resources) to the calling function, or storing it in a structure that was passed to the current function, or copying it to a global or (file) static variable, or even stashing it in a (function) static variable so if the function is called again, it has some resource available on entry.