12.3. Resizing and Releasing MemoryWhen you no longer need a dynamically allocated memory block, you should give it back to the operating system. You can do this by calling the function free( ). Alternatively, you can increase or decrease the size of an allocated memory block by calling the function realloc( ). The prototypes of these functions are as follows:
The pointer argument that you pass to either of the functions free( ) and realloc( )if it is not a null pointermust be the starting address of a dynamically allocated memory block that has not yet been freed. In other words, you may pass these functions only a null pointer or a pointer value obtained from a prior call to malloc( ), calloc( ), or realloc( ). If the pointer argument passed to free( ) or realloc( ) has any other value, or if you try to free a memory block that has already been freed, the program's behavior is undefined. The memory management functions keep internal records of the size of each allocated memory block. This is why the functions free( ) and realloc( ) require only the starting address of the block to be released, and not its size. There is no way to test whether a call to the free( ) function is successful, because it has no return value. The function getline( ) in Example 12-1 is another variant of the function defined with the same name in Example 9-4. It reads a line of text from standard input and stores it in a dynamically allocated buffer. The maximum length of the line to be stored is one of the function's parameters. The function releases any memory it doesn't need. The return value is a pointer to the line read. Example 12-1. The getline( ) function// Read a line of text from stdin into a dynamically allocated buffer. // Replace the newline character with a string terminator. // // Arguments: The maximum line length to read. // Return value: A pointer to the string read, or // NULL if end-of-file was read or if an error occurred. char *getline( unsigned int len_max ) { char *linePtr = malloc( len_max+1 ); // Reserve storage for "worst case." if ( linePtr != NULL ) { // Read a line of text and replace the newline characters with // a string terminator: int c = EOF; unsigned int i = 0; while ( i < len_max && ( c = getchar( ) ) != '\n' && c != EOF ) linePtr[i++] = (char)c; linePtr[i] = '\0'; if ( c == EOF && i == 0 ) // If end-of-file before any { // characters were read, free( linePtr ); // release the whole buffer. linePtr = NULL; } else // Otherwise, release the unused portion. linePtr = realloc( linePtr, i+1 ); // i is the string length. } return linePtr; } The following code shows how you might call the getline( ) function: char *line; if (( line = getline(128) ) != NULL ) // If we can read a line, { /* ... */ // process the line, free( line ); // then release the buffer. } |