c pointer, how to free it/them into a function - c

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:
char *host = 0;
char *user = 0;
When using realloc(), do not assign the result to the expression passed as the first parameter:
Do NOT do:
ptr = realloc(ptr, newsize);
If (when) ptr is 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:
void *newptr = realloc(oldptr, newsize);
if (newptr == 0)
...recover from memory allocation failure
oldptr = newptr;
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.

As a few people have pointed out, modern OS's reclaim memory on exit. However, it is considered a best practice to free your resources anyway, as this makes debugging easier. For example, if you are trying to find a leak and you use a tool like valgrind, all the memory you don't properly free (even if by the program logic, this doesn't matter) will appear as leaks. There are some large API's around that notoriously don't do this, and they make tracking leaks in applications which use them a nightmare.
Also, in some specialized environments it might be important to clean up after yourself. Therefore, it's a good habit to get into now.
A clean-up technique you'll see occasionally (eg, in the linux kernel) is something I think of as the "bail and release" pattern. It's one of the few (perhaps: only) contexts where goto is still considered acceptable. It depends upon you being able to free your resources in the opposite order you allocated them. Usually this is in the context of a single function, in this case main():
#include <stdlib.h>
int main(void) {
int exit_status = EXIT_FAILURE;
char *s1, *s2, *s3;
s1 = malloc(100);
if (!s1) return EXIT_FAILURE;
s2 = malloc(100);
if (!s2) goto endB;
s3 = malloc(100);
if (!s3) goto endA;
exit_status = EXIT_SUCCESS;
/* do whatever */
free(s3);
endA:
free(s2);
endB:
free(s1);
return exit_status;
}
To explain: if allocating s1 fails, we just return -- there is nothing to clean-up. But if allocating s2 fails, we goto endB, freeing s1. If allocating s3 fails, we goto endA, which will free s2 and s1. Finally, if everything succeeded, we do whatever, and afterward, all three pointers will be freed. If this were a normal function, we might be returning a pointer, so there would be a separate return for that before the "end" bits, which would complete with "return null" instead.
Nb: please don't take this as a licence to make free-wheeling use of goto!

Yeah, you don't have to free anything if this is the whole program.
The whole reason to free memory is so it can be reused somewhere later in the program. Even if your program went on from this point, you've only allocated a small number of bytes. It's OK to allocate them and keep them forever.
In fact, you don't even have to do the arithmetic you're doing there to carve out exact-sized mallocs, you could say Oh, usernames and hostnames are never more than like 30 chars, just to be sure I'll allocate 256 char blocks. Oh wait your max is 8 chars, whatever. Or even just make a global buffer 256 chars or 8 chars long. Then make sure your strncpy()s never go past len_max or else you're risking a buffer overflow hack.
meanwhile that getinfo() looks painful. Try something like fgets(mybuffer, len_max, stdin).
Last I checked, the executable doesn't even bother to 'free' all unfreed blocks at the end, it just walks away. The VM system returns all the used memory (including the stack and program code) to the OS, and the process vaporizes and it's over. The malloc()ed blocks are just a pattern of bytes on that memory, and it's all forgotten.

This is more of a general C language advice than a specific answer, but it's too long to go in comment.
The usual way to write C in the presence of dynamic resource management is to goto suitable labels which are followed by the relevant deallocation calls:
int f(int n)
{
void * p1, * p2, * p3;
int result = -1;
p1 = malloc(n);
if (!p1) goto END0;
if (n % 2) goto END1;
p2 = malloc(3 * n);
if (!p2) goto END1;
if (n % 7 == 0) goto END2;
p3 = malloc(7 * n + 8);
if (!p3) goto END2;
if (do_useful_stuff(p1, p2, p3) == -1) goto END3;
result = compute_more_stuff(p1, p2, p3);
END3:
free(p3);
END2:
free(p2);
END1:
free(p1);
END0:
return result;
}
The alternative is to split up your code into very small functions that do only one thing at a time and handle resource allocation in an ad-hoc fashion:
int small_function(void ** p)
{
void * q = malloc(13);
if (some_init(&q) == -1)
{
free(q); // ad-hoc exit management
return -1;
}
int n = complex_computation(q);
free(q);
return n;
}

You don't have to free dynamically allocated memory before exiting. The OS will make all that memory available to the next process.

Related

Problem with error checking for every malloc call?

I'm writing a simple utility in C and I'm writing codes to print error messages in STDERR.
I have a struct, defined as:
struct arguments
{
FILE *source;
int modifier_value;
int filesize;
};
I have declared a pointer to the above struct, and allocated memory to it:
struct arguments *arg = NULL;
arg = malloc(sizeof(struct arguments));
if(arg == NULL)
{
fprintf(stderr, "error: malloc - %s\n", strerror(errno)); //I know i could use perror as well, but I like the convention of using fprintf() for both stdout, stderr, and other file streams, just for symmetry
return EXIT_FAILURE;
}
As you can see, I have only allocated memory sufficient to store one object of type struct arguments and I still error checking for it.
The problem is I have many pointers like that which points to space of one object, and error checking all of them just increases number of codes and affects readability of code.
Is it a "good practice" / "is it ok" if I ignore error checking just for the reason that I'm not allocating memory too much memory (I heard something about paging and I think system combines many pages if I request for too much memory and chances of error in that case would be high, but not for memory request of something like 64 bytes).
Is it a "good practice" / "is it ok" if I ignore error checking just for the reason that I'm not allocating memory too much memory
It is poor practice to fail to error-check function calls that report on errors, except where you don't care whether the call succeeded. And you always care whether malloc() succeeds, or else you shouldn't be calling it in the first place. You don't know whether you are allocating too much memory unless you check whether your malloc() calls succeed.
The problem is I have many pointers like that which points to space of one object, and error checking all of them just increases number of codes and affects readability of code.
In the first place, use dynamic allocation only where you actually need it. Some people seem to have the idea that they need dynamic allocation wherever they want a pointer to an object. This absolutely is not the case. You need pointers if you are performing dynamic allocation, but you don't necessarily need dynamic allocation where you use pointers. Very often, static or automatic allocation can be combined with the address-of operator (unary &) instead. For example:
{
struct arguments arg = {0};
init_arguments(&arg);
do_something(&arg);
// all done with arg
}
You need dynamic allocation only when (i) you do not know at compile time how much memory you will need, or (ii) you need an object whose lifetime extends past the termination of the innermost block enclosing its creation.
When you really do need dynamic allocation, you can reduce the amount of boilerplate code by using a macro or a wrapper function. Similar applies to performing other success checks. For example, use a function such as this instead of using malloc() directly:
void *checked_malloc(size_t size) {
void *result = malloc(size);
if (result == NULL && size != 0) {
fputs("error: malloc failed -- aborting...\n", stderr);
abort();
}
return result;
}
Create allocation wrapper functions to make always checking allocation success easy.
To expand on #Weather Vane idea of passing an argument to identify the caller, yet do it in a macro wrapper.
my_malloc.h
#ifndef MY_MALLOC
#define MY_MALLOC(size) my_malloc((size), __FUNC__, __LINE__)
#include <stdlib.h>
// Return a valid allocation or don't return.
void *my_malloc(size_t size, const char *func, unsigned line);
#endif
my_malloc.c
#include "my_maloc.h"
#include <stdio.h>
#include <stdlib.h>
void *my_malloc(size_t size, const char *func, unsigned line) {
if (size == 0) {
return NULL;
}
void *ptr = malloc(size);
if (ptr == NULL) {
fprintf(stderr, "Failed to allocate %zu bytes at \"%s()\", line %u\n",
size, func, line);
exit(EXIT_FAILURE);
}
return ptr;
}
user_code.c
#include "my_malloc.h"
...
// No need to explicitly pass the function name, line number
arg = MY_MALLOC(sizeof *arg * n);
// Error checking not needed.
...
free(arg);
I'd even consider a matching MY_FREE where freeing passes in the pointer and the expected size. Then those 2 routines could keep allocation statistics, free size validation, ...
If you have many objects, you cam allocate memory for all immediately:
void *pvc;
pvc = malloc(how_many_for_all);
and then consecutively declare pointers to objects like this:
Obj1 *p1;
Obj2 *p2;
Obj3 *p3;
p1 = (Obj1)pvc;
p2 = (Obj2)(pvc + sizeof(Obj1));
p3 = (Obj3)(pvc + sizeof(Obj1) + sizeof(Obj2));
This is pseudocode sooner. Compiler will be make warnings, but this works.

Memory Allocation, Recursive Function and Pure C [duplicate]

I know that on your hard drive, if you delete a file, the data is not (instantly) gone. The data is still there until it is overwritten. I was wondering if a similar concept existed in memory. Say I allocate 256 bytes for a string, is that string still floating in memory somewhere after I free() it until it is overwritten?
Your analogy is correct. The data in memory doesn't disappear or anything like that; the values may indeed still be there after a free(), though attempting to read from freed memory is undefined behaviour.
Generally, it does stay around, unless you explicitly overwrite the string before freeing it (like people sometimes do with passwords). Some library implementations automatically overwrite deallocated memory to catch accesses to it, but that is not done in release mode.
The answer depends highly on the implementation. On a good implementation, it's likely that at least the beginning (or the end?) of the memory will be overwritten with bookkeeping information for tracking free chunks of memory that could later be reused. However the details will vary. If your program has any level of concurrency/threads (even in the library implementation you might not see), then such memory could be clobbered asynchronously, perhaps even in such a way that even reading it is dangerous. And of course the implementation of free might completely unmap the address range from the program's virtual address space, in which case attempting to do anything with it will crash your program.
From a standpoint of an application author, you should simply treat free according to the specification and never access freed memory. But from the standpoint of a systems implementor or integrator, it might be useful to know (or design) the implementation, in which case your question is then interesting.
If you want to verify the behaviour for your implementation, the simple program below will do that for you.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* The number of memory bytes to test */
#define MEM_TEST_SIZE 256
void outputMem(unsigned char *mem, int length)
{
int i;
for (i = 0; i < length; i++) {
printf("[%02d]", mem[i] );
}
}
int bytesChanged(unsigned char *mem, int length)
{
int i;
int count = 0;
for (i = 0; i < MEM_TEST_SIZE; i++) {
if (mem[i] != i % 256)
count++;
}
return count;
}
main(void)
{
int i;
unsigned char *mem = (unsigned char *)malloc(MEM_TEST_SIZE);
/* Fill memory with bytes */
for (i = 0; i < MEM_TEST_SIZE; i++) {
mem[i] = i % 256;
}
printf("After malloc and copy to new mem location\n");
printf("mem = %ld\n", mem );
printf("Contents of mem: ");
outputMem(mem, MEM_TEST_SIZE);
free(mem);
printf("\n\nAfter free()\n");
printf("mem = %ld\n", mem );
printf("Bytes changed in memory = %d\n", bytesChanged(mem, MEM_TEST_SIZE) );
printf("Contents of mem: ");
outputMem(mem, MEM_TEST_SIZE);
}

Freeing malloced structure in a function

I'm creating a source files containing buffer functionality that I want to use for my other library that I'm creating.
It is working correctly but I'm having trouble getting rid of the buffer structure that I'm creating in one of the functions. The following snippets should help illustrate my problem:
C header:
//dbuffer.h
...
typedef struct{
char *pStorage;
int *pPosition;
int next_position;
int number_of_strings;
int total_size;
}DBUFF;
...
C source:
//dbuffer.c
...
DBUFF* dbuffer_init(char *init_pArray)
{
//Find out how many elements the array contains
int size = sizeof_pArray(init_pArray);
//Initialize buffer structure
DBUFF *buffer = malloc(sizeof(DBUFF));
//Initialize the storage
buffer->pStorage = malloc( (sizeof(char)) * (size) );
strncpy( &(buffer->pStorage)[0] , &init_pArray[0] , size);
buffer->number_of_strings = 1;
buffer->total_size = size;
buffer->next_position = size; //size is the next position because array allocates elements from 0 to (size-1)
//Initialize the position tracker which keeps record of starting position for each string
buffer->pPosition = malloc(sizeof(int) * buffer->number_of_strings );
*(buffer->pPosition + (buffer->number_of_strings -1) ) = 0;
return buffer;
}
void dbuffer_destroy(DBUFF *buffer)
{
free(buffer->pStorage);
free(buffer);
}
...
Main:
#include <stdio.h>
#include <stdlib.h>
#include "dbuffer.h"
int main(int argc, char** argv)
{
DBUFF *buff;
buff = dbuffer_init("Bring the action");
dbuffer_add(buff, "Bring the apostles");
printf("BUFFER CONTENTS: ");
dbuffer_print(buff);
dbuffer_destroy(buff);
// Looks like it has been succesfully freed because output is garbage
printf("%s\n", buff->pStorage);
//Why am I still able to access struct contents after the pointer has been freed ?
printf("buff total size: %d\n", buff->total_size);
return (EXIT_SUCCESS);
}
Output:
BUFFER CONTENTS: Bring the action/0Bring the apostles/0
��/�
buff total size: 36
RUN SUCCESSFUL (total time: 94ms)
Question:
Why am I still able to access struct contents using the line below after the pointer to the struct has been freed ?
printf("buff total size: %d\n", buff->total_size);
Once you've called free() on the allocated pointer, attempt to make use of the pointer invokes undefined behavior. You should not be doing that.
To quote C11 standard, chapter §7.22.3.4, free() function
The free() function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. [..]
It never say's anything about a cleanup, which you might be (wrongly) expecting.
Just to add clarity, calling free() does not always actually free up the allocated physical memory. It just enables that pointer (memory space) to be allocated again (returning the same pointer, for example) for successive calls to malloc() and family. After calling free(), that pointer is not supposed to be used from your program anymore but C standard does not guarantee of a cleanup of the allocated memory.
If any attempt is made to read memory that has been freed can crash your program. Or they might not. As far as the language is concerned, its undefined behaviour.
Your compiler won't warn you about it(or stop you from accessing it). But clearly don't do this after calling free -
printf("buff total size: %d\n", buff->total_size);
As a good practice you can set the freed pointer to NULL .
free() call will just mark the memory in heap as available for use. So you still have the pointer pointing to this memory location but it's not available anymore for you. Thus, the next call to malloc() is likely to assign this memory to the new reservation.
To void this situations normally once you free() the memory allocated to a pointer you should set it to NULL. De-referencing NULL is UB also but at least when debugging you can see tha pointer should not be used because it's not pointing to a valid memory address.
[too long for a comment]
To allow your "destructor" to set the pointer passed to NULL modify your code like this:
void dbuffer_destroy(DBUFF ** buffer)
{
if ((NULL == buffer) || (NULL == *buffer))
{
return;
}
free((*buffer)->pPosition);
free((*buffer)->pStorage);
free(*buffer);
*buffer = NULL;
}
and call it like this:
...
dbuffer_destroy(&buff);
...

Strange (Undefined?) Behavior of Free in C

This is really strange... and I can't debug it (tried for about two hours, debugger starts going haywire after a while...). Anyway, I'm trying to do something really simple:
Free an array of strings. The array is in the form:
char **myStrings. The array elements are initialized as:
myString[index] = malloc(strlen(word));
myString[index] = word;
and I'm calling a function like this:
free_memory(myStrings, size); where size is the length of the array (I know this is not the problem, I tested it extensively and everything except this function is working).
free_memory looks like this:
void free_memory(char **list, int size) {
for (int i = 0; i < size; i ++) {
free(list[i]);
}
free(list);
}
Now here comes the weird part. if (size> strlen(list[i])) then the program crashes. For example, imagine that I have a list of strings that looks something like this:
myStrings[0] = "Some";
myStrings[1] = "random";
myStrings[2] = "strings";
And thus the length of this array is 3.
If I pass this to my free_memory function, strlen(myStrings[0]) > 3 (4 > 3), and the program crashes.
However, if I change myStrings[0] to be "So" instead, then strlen(myStrings[0]) < 3 (2 < 3) and the program does not crash.
So it seems to me that free(list[i]) is actually going through the char[] that is at that location and trying to free each character, which I imagine is undefined behavior.
The only reason I say this is because I can play around with the size of the first element of myStrings and make the program crash whenever I feel like it, so I'm assuming that this is the problem area.
Note: I did try to debug this by stepping through the function that calls free_memory, noting any weird values and such, but the moment I step into the free_memory function, the debugger crashes, so I'm not really sure what is going on. Nothing is out of the ordinary until I enter the function, then the world explodes.
Another note: I also posted the shortened version of the source for this program (not too long; Pastebin) here. I am compiling on MinGW with the c99 flag on.
PS - I just thought of this. I am indeed passing numUniqueWords to the free function, and I know that this does not actually free the entire piece of memory that I allocated. I've called it both ways, that's not the issue. And I left it how I did because that is the way that I will be calling it after I get it to work in the first place, I need to revise some of my logic in that function.
Source, as per request (on-site):
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "words.h"
int getNumUniqueWords(char text[], int size);
int main(int argc, char* argv[]) {
setvbuf(stdout, NULL, 4, _IONBF); // For Eclipse... stupid bug. --> does NOT affect the program, just the output to console!
int nbr_words;
char text[] = "Some - \"text, a stdin\". We'll have! also repeat? We'll also have a repeat!";
int length = sizeof(text);
nbr_words = getNumUniqueWords(text, length);
return 0;
}
void free_memory(char **list, int size) {
for (int i = 0; i < size; i ++) {
// You can see that printing the values is fine, as long as free is not called.
// When free is called, the program will crash if (size > strlen(list[i]))
//printf("Wanna free value %d w/len of %d: %s\n", i, strlen(list[i]), list[i]);
free(list[i]);
}
free(list);
}
int getNumUniqueWords(char text[], int length) {
int numTotalWords = 0;
char *word;
printf("Length: %d characters\n", length);
char totalWords[length];
strcpy(totalWords, text);
word = strtok(totalWords, " ,.-!?()\"0123456789");
while (word != NULL) {
numTotalWords ++;
printf("%s\n", word);
word = strtok(NULL, " ,.-!?()\"0123456789");
}
printf("Looks like we counted %d total words\n\n", numTotalWords);
char *uniqueWords[numTotalWords];
char *tempWord;
int wordAlreadyExists = 0;
int numUniqueWords = 0;
char totalWordsCopy[length];
strcpy(totalWordsCopy, text);
for (int i = 0; i < numTotalWords; i++) {
uniqueWords[i] = NULL;
}
// Tokenize until all the text is consumed.
word = strtok(totalWordsCopy, " ,.-!?()\"0123456789");
while (word != NULL) {
// Look through the word list for the current token.
for (int j = 0; j < numTotalWords; j ++) {
// Just for clarity, no real meaning.
tempWord = uniqueWords[j];
// The word list is either empty or the current token is not in the list.
if (tempWord == NULL) {
break;
}
//printf("Comparing (%s) with (%s)\n", tempWord, word);
// If the current token is the same as the current element in the word list, mark and break
if (strcmp(tempWord, word) == 0) {
printf("\nDuplicate: (%s)\n\n", word);
wordAlreadyExists = 1;
break;
}
}
// Word does not exist, add it to the array.
if (!wordAlreadyExists) {
uniqueWords[numUniqueWords] = malloc(strlen(word));
uniqueWords[numUniqueWords] = word;
numUniqueWords ++;
printf("Unique: %s\n", word);
}
// Reset flags and continue.
wordAlreadyExists = 0;
word = strtok(NULL, " ,.-!?()\"0123456789");
}
// Print out the array just for funsies - make sure it's working properly.
for (int x = 0; x <numUniqueWords; x++) {
printf("Unique list %d: %s\n", x, uniqueWords[x]);
}
printf("\nNumber of unique words: %d\n\n", numUniqueWords);
// Right below is where things start to suck.
free_memory(uniqueWords, numUniqueWords);
return numUniqueWords;
}
You've got an answer to this question, so let me instead answer a different question:
I had multiple easy-to-make mistakes -- allocating a wrong-sized buffer and freeing non-malloc'd memory. I debugged it for hours and got nowhere. How could I have spent that time more effectively?
You could have spent those hours writing your own memory allocators that would find the bug automatically.
When I was writing a lot of C and C++ code I made helper methods for my program that turned all mallocs and frees into calls that did more than just allocate memory. (Note that methods like strdup are malloc in disguise.) If the user asked for, say, 32 bytes, then my helper method would add 24 to that and actually allocate 56 bytes. (This was on a system with 4-byte integers and pointers.) I kept a static counter and a static head and tail of a doubly-linked list. I would then fill in the memory I allocated as follows:
Bytes 0-3: the counter
Bytes 4-7: the prev pointer of a doubly-linked list
Bytes 8-11: the next pointer of a doubly-linked list
Bytes 12-15: The size that was actually passed in to the allocator
Bytes 16-19: 01 23 45 67
Bytes 20-51: 33 33 33 33 33 33 ...
Bytes 52-55: 89 AB CD EF
And return a pointer to byte 20.
The free code would take the pointer passed in and subtract four, and verify that bytes 16-19 were still 01 23 45 67. If they were not then either you are freeing a block you did not allocate with this allocator, or you've written before the pointer somehow. Either way, it would assert.
If that check succeeded then it would go back four more and read the size. Now we know where the end of the block is and we can verify that bytes 52 through 55 are still 89 AB CD EF. If they are not then you are writing over the end of a block somewhere. Again, assert.
Now that we know that the block is not corrupt we remove it from the linked list, set ALL the memory of the block to CC CC CC CC ... and free the block. We use CC because that is the "break into the debugger" instruction on x86. If somehow we end up with the instruction pointer pointing into such a block it is nice if it breaks!
If there is a problem then you also know which allocation it was, because you have the allocation count in the block.
Now we have a system that finds your bugs for you. In the release version of your product, simply turn it off so that your allocator just calls malloc normally.
Moreover you can use this system to find other bugs. If for example you believe that you've got a memory leak somewhere all you have to do is look at the linked list; you have a complete list of all the outstanding allocations and can figure out which ones are being kept around unnecessarily. If you think you're allocating too much memory for a given block then you can have your free code check to see if there are a lot of 33 in the block that is about to be freed; that's a sign that you're allocating your blocks too big. And so on.
And finally: this is just a starting point. When I was using this debug allocator professionally I extended it so that it was threadsafe, so that it could tell me what kind of allocator was doing the allocation (malloc, strdup, new, IMalloc, etc.), whether there was a mismatch between the alloc and free functions, what source file contained the allocation, what the call stack was at the time of the allocation, what the average, minimum and maximum block sizes were, what subsystems were responsible for what memory usage...
C requires that you manage your own memory; this definitely has its pros and cons. My opinion is that the cons outweigh the pros; I much prefer to work in automatic storage languages. But the nice thing about having to manage your own storage is that you are free to build a storage management system that meets your needs, and that includes your debugging needs. If you must use a language that requires you to manage storage, use that power to your advantage and build a really powerful subsystem that you can use to solve professional-grade problems.
The problem is not how you're freeing, but how you're creating the array. Consider this:
uniqueWords[numUniqueWords] = malloc(strlen(word));
uniqueWords[numUniqueWords] = word;
...
word = strtok(NULL, " ,.-!?()\"0123456789");
There are several issues here:
word = strtok(): what strtok returns is not something that you can free, because it has not been malloc'ed. ie it is not a copy, it just points to somewhere inside the underlying large string (the thing you called strtok with first).
uniqueWords[numUniqueWords] = word: this is not a copy; it just assigns the pointer. the pointer which is there before (which you malloc'ed) is overwritten.
malloc(strlen(word)): this allocates too little memory, should be strlen(word)+1
How to fix:
Option A: copy properly
// no malloc
uniqueWords[numUniqueWords] = strdup(word); // what strdup returns can be free'd
Option B: copy properly, slightly more verbose
uniqueWords[numUniqueWords] = malloc(strlen(word)+1);
strcpy(uniqueWords[numUniqueWords], word); // use the malloc'ed memory to copy to
Option C: don't copy, don't free
// no malloc
uniqueWords[numUniqueWords] = word; // not a copy, this still points to the big string
// don't free this, ie don't free(list[i]) in free_memory
EDIT As other have pointed out, this is also problematic:
char *uniqueWords[numTotalWords];
I believe this is a GNU99 extension (not even C99), and indeed you cannot (should not) free it. Try char **uniqueWords = (char**)malloc(sizeof(char*) * numTotalWords). Again the problem is not the free() but the way you allocate. You are on the right track with the free, just need to match every free with a malloc, or with something that says it is equivalent to a malloc (like strdup).
You are using this code in an attempt to allocate the memory:
uniqueWords[numUniqueWords] = malloc(strlen(word));
uniqueWords[numUniqueWords] = word;
numUniqueWords++;
This is wrong on many levels.
You need to allocate strlen(word)+1 bytes of memory.
You need to strcpy() the string over the allocated memory; at the moment, you simply throw the allocated memory away.
Your array uniqueWords is itself not allocated, and the word values you have stored are from the original string which has been mutilated by strtok().
As it stands, you cannot free any memory because you've already lost the pointers to the memory that was allocated and the memory you are trying to free was never in fact allocated by malloc() et al.
And you should be error checking the memory allocations too. Consider using strdup() to duplicate strings.
You are trying to free char *uniqueWords[numTotalWords];, which is not allowed in C.
Since uniqueWords is allocated on the stack and you can't call free on stack memory.
Just remove the last free call, like this:
void free_memory(char **list, int size) {
for (int i = 0; i < size; i ++) {
free(list[i]);
}
}
Proper way of allocating and deallocating char array.
char **foo = (char **) malloc(row* sizeof(char *));
*foo = malloc(row * col * sizeof(char));
for (int i = 1; i < row; i++) {
foo[i] = *foo + i*col;
}
free(*foo);
free(foo);
Note that you don't need to go through each & every element of the array for deallocation of memory. Arrays are contiguous so call free on the name of the array.

Is there a memory leak in my code? (using pointers to store strings)

#include <stdio.h>
#include <stdlib.h>
int main(void) {
int x;
int *in, *begin;
in = (int *)malloc(sizeof(int));
begin = in;
while ((x = getchar()) != EOF) {
*in = x;
in++;
in = (int *)malloc(sizeof(int));
}
*in = EOF;
while ((x = *begin) != EOF) {
putchar(x);
begin++;
}
free(in);
return 0;
}
I have a sneaking suspicion that it does.
With this program, I'm trying to store user input of an indefinite size into memory using pointers, as opposed to using char string[255]; fgets(string, sizeof(string)); etc.
EDIT: The program doesn't crash or anything when I run it, I just have a feeling there's memory getting allocated that isn't getting freed.
Yes, the program has a memory leak.
int *in, *begin;
in = (int *)malloc(sizeof(int)); /* allocate space for 1 int, at location "X" */
begin = in;
while ((x = getchar()) != EOF) {
*in = x;
in++; /* "in" increments address (to location) "X+1" */
in = (int *)malloc(sizeof(int)); /* address "X+1" is lost as malloc returns
a different memory location, *not*
necessarily at "X+2". Access to
previous data other than pointed to by
"begin" is lost */
}
*in = '\0'; /* this makes probably more senese than assigining EOF here */
There needs to be corresponding calls to free() when you allocate memory.
Also, I don't think the input is stored correctly.
in is never given a continious block of memory to store the data. Instead a single memory location of size to store an int is repeatedly allocated and assigned to in, but we don't really know where this memory is, so all of these allocations are lost since only a single pointer in is keeping track of them.
In other words, the leak consists of repeatedly allocating memory for the size of an int, assigning it to in, and then losing any reference to that location next time through the loop.
Variable begin initially points at the first item entered, but then subsequently trapses through unknown memory as its pointer value is incremented by 1 repeatedly in the output loop.
A better approach would be to allocate a single, larger continuous buffer once at the start and then use it as you increment your in pointer, or to start with a smaller amount but then monitor memory use and realloc() more as needed (but much more overhead to save a few byes of memory).
Also, at the end of your first loop rather than assigning EOF to in, it would make more sense to put in a null character.
Finally, the free(in) call at the bottom of the program frees only a single memory location, none of the other previously allocated memory.
Here's a quickly put together version that works, I tried to make minimal changes to the original code and to keep your code structure intact (I am sure you had your reasons for writing it this way with two loops in the first place) though this could be written much more compactly with just one loop.
Note I initially allocate space for 100 characters, adjust this according to your needs, or alternatively allocate less initially, but then keep track of memory consumption and realloc() more memory as you need (which I think was your initial intention, but just not implemented quite correctly).
int main(void) {
int x;
int *in, *begin;
int *start_loc;
in = (int *)malloc(sizeof(int) * 100); /* continious space */
begin = in;
start_loc = in; /* keep track of start location for final free() call */
while ((x = getchar()) != EOF) {
*in = x;
in++;
}
*in = 0; /* terminator for the input string/data */
while (*begin != 0) { /* simplified */
putchar(*begin);
begin++;
}
free(start_loc); /* free allocated memory */
return 0;
}
This could be written without the use of a new variable start_loc (by reusing in for instance) but I chose to write it this way to emphasize the importance of keeping track of the start of your memory allocation and the ability to correctly free memory allocated, so to address your memory leak problem.
Yes you have. Free will deallocate memory for one only integer. You have to call free for every malloc call you have done.
Also to store the characters in a continuous buffer you have to malloc an amount of memory at the beginning and use realloc if the characters you read become more than those initially allocated memory for.
Also don't forget to allocate one more character for the \0 at the end of the string.
When you are done you can call free(buffer) and... Success! No memory leaks!
And the code for it:
/* Start with an initial size */
int size = 128;
char *buffer = (char *)malloc(size + 1);
int i = 0;
while ((x = getchar()) != EOF) {
buffer[i] = x;
i++;
if(i == size){
/*Do realloc and increase size */
}
}
buffer[i] = '\0';
/* Do what you want with buffer */
free(buffer);
Of course there is a memory leak, for every call to malloc there sould be a corresponding call to free in your program.
In your program malloc is called several times but there is only one call to free.
Levon's answer is correct. You increase the value of in here:
in++;
...but then you reassign it to an address that is arbitrary here:
in = (int *)malloc(sizeof(int));
To achieve what you're trying to do you either need to:
Allocate a large chunk of contiguous memory in one go, and realloc() whenever it needs to expand (this is what you're trying to achieve), or;
Use linked lists to navigate through a list of non-contiguous memory addresses (this is what you've actually managed to write).
When you use malloc to allocate memory, you should make sure that the pointer which point to the memory is not NULL, and after you free the memory, you are better to set the pointer to NULL

Resources