Realloc used with free - c

I am trying to use realloc function to store input characters in a dynamically array. Everything goes fine when I use it without calling free method to release the memory after usage. But when I use it with free method runtime error comes. Here is my code snippet.
int main(){
char *message ;
int len = 0 ;
char c ;
while((c=getchar()) != '\n'){
message = realloc(message,(len+1)*sizeof(char)) ;
message[len++] = c ;
}
message = realloc(message, (len+1)* sizeof(char));
message[len]='\0' ;
printf("Message is %s\n",message);
free(message) ;
return 0 ;
}
Can anyone figure out this. As i need to use both method together..
Thanks!!!!

Though it may not be causing the problem you're seeing, X = realloc(X, newsize); is a timebomb waiting to explode. realloc can return a null pointer and leave your existing data unchanged if it fails to allocate the new chunk you've asked for. When/if it does that, this will overwrite the existing pointer with NULL, leaking the memory you've previously allocated (and failing to allocate more).
Though it's probably not causing the problem either, I'd also recommend (strongly) against using realloc to increase your allocation one character at a time. That's horribly inefficient. I'd start with a block of, say, 32 or 64 characters, and increase the allocation by some factor (say, 1.5) each time you run out of space. This way you can deal with greatly different lengths of input without a huge number of calls to realloc.
Edit: looking at it, the real problem probably that you haven't initialized your pointer properly before the initial call to realloc. If you pass something other than a NULL pointer, it expects what you're passing to be a valid pointer you got from malloc/calloc or a previous call to realloc.
int main(){
char *message ;
int len = 0 ;
char c ;
while((c=getchar()) != '\n'){
message = realloc(message,(len+1)*sizeof(char)) ;
message[len++] = c ;
}
message = realloc(message, (len+1)* sizeof(char));
message[len]='\0' ;
printf("Message is %s\n",message);
free(message) ;
return 0 ;
}
At least for me, this runs without any error messages.

Related

Segmentation fault on program with scanf

This is a small piece of code that I made while trying to understand how malloc and pointers work.
#include <stdio.h>
#include <stdlib.h>
int *buffer (int count)
{
int *buffer = malloc (count * sizeof(int));
for (int i = 0; 0 <= i && i < count; i++)
{
buffer[i] = 0;
}
return &buffer;
}
int main ()
{
int size = 0;
int i = 0;
scanf ("%d", &size);
int *num = buffer (size);
while (i < size)
{
scanf ("%d", &num[i]);
i++;
}
}
For some reason that I can't understand, I keep getting a segmentation fault. This error repeatedly happens on the last scanf() and I do not know why. I know i have to pass pointer to scan f and num is already a pointer so i thought that i would not need to include the &. But, I received a segmentation fault earlier if i do not. Also, I believe I have allocated the correct amount of space using malloc but I am not sure. Any help with what is happening here would be appreciated.
You returned the pointer to the local variable buffer, which will banish on exiting the function buffer.
You should remove the & used in the return statement and return the pointer to allocated buffer.
Also checking whether malloc() is successful should be added.
There are a couple of issues that I can see, and one of them is definitely a problem.
In function, int *buffer (int count)
return &buffer;
This will return address of buffer which is already a local int * variable.
So when the return happens, variable buffer would no longer be valid. Hence, the address is invalid.
One of the ways to go ahead as of now would be avoiding a function call buffer and using calloc().
Because, subject to availability, calloc() will allocate the memory of requested length, which will be initialized to 0 by default.
Or, the other way would be making the buffer pointer a global variable.
Also, with existing implementation, there needs a piece of code which checks if malloc returned anything or not. That would indicate if the memory was allocated or not.
Something like this would do:
int *buffer = malloc (count * sizeof(int));
if(buffer == NULL)
{
// Some error handling
return 0;
}
Additionally, I see the for loop which looks a bit weird than what it should look like:
for (int i = 0; 0 <= i && i < count; i++)
I take that you are trying to loop the count times and fill a 0 in buffer. This could have been achieved by
for (int i = 0; i < count; i++)
So, a malloc() is followed by en error-check and then followed by a for to fill the allocated memory with zeroes. So, using calloc makes life a lot easier.
Importantly, you allocate memory but you don't seem to have a code that de-allocates (frees) it. There are ample of examples to refer for doing that. I would recommend you to read concepts like Memory Leakage, Dangling Pointers and using valgrind or similar thing to validate the memory usage.
As a side-note and not a rule of thumb, always make sure that the names you use for variables are different than the names you use with functions. That creates a hell a lot of confusion. Going ahead with existing naming habit, you'll have a tough day when the code is reviewed.

Initialize a 16mb array in C

I am relatively new to 'C' and would appreciate some insight on this topic.
Basically, I am trying to create a 16 MB array and check if the memory content is initialized to zero or '\0' or some garbage value for a school project.
Something like this:
char buffer[16*1024*1024];
I know there is a limit on the size of the program stack and obviously I get a segmentation fault. Can this somehow be done using malloc()?
You can initialize the memory with malloc like so:
#define MEM_SIZE_16MB ( 16 * 1024 * 1024 )
char *buffer = malloc(MEM_SIZE_16MB * sizeof(char) );
if (buffer == NULL ) {
// unable to allocate memory. stop here or undefined behavior happens
}
You can then check the values in memory so (note that this will print for a very very long time):
for (int i = 0; i < MEM_SIZE_16MB; i++) {
if( i%16 == 0 ) {
// print a newline and the memory address every 16 bytes so
// it's a little easier to read
printf("\nAddr: %08p: ", &buffer[i]);
}
printf("%02x ", buffer[i]);
}
printf("\n"); // one final newline
Don't forget to free the memory when finished
free(buffer);
Yes, you will probably need to do this using malloc(), and here's why:
When any program (process ... thread ...) is started, it is given a chunk of memory which it uses to store (among other things ...) "local" variables. This area is called "the stack." It most-certainly won't be big enough to store 16 megabytes.
But there's another area of memory which any program can use: its "heap." This area (as the name, "heap," is intended to imply ...) has no inherent structure: it's simply a pool of storage, and it's usually big enough to store many megabytes. You simply malloc() the number of bytes you need, and free() those bytes when you're through.
Simply define a type that corresponds to the structure you need to store, then malloc(sizeof(type)). The storage will come from the heap. (And that, basically, is what the heap is for ...)
Incidentally, there's a library function called calloc() which will reserve an area that is "known zero." Furthermore, it might use clever operating-system tricks to do so very efficiently.
Sure:
int memSize = 16*1024*1024;
char* buffer = malloc( memSize );
if ( buffer != 0 )
{
// check contents
for ( i = 0; i < memSize; i++ )
{
if ( buffer[i] != 0 )
{
// holler
break;
}
}
free( buffer );
}
Strictly speaking, code can not check if buffer is not zeroed without risking undefined behavior. Had the type been unsigned char, then no problem. But char, which may be signed, may have a trap value. Attempting to work with that value leads to UB.
char buffer[16*1024*1024];
// Potential UB
if (buffer[0]) ...
Better to use unsigned char which cannot have trap values.
#define N (16LU*1204*1204)
unsigned char *buffer = malloc(N);
if (buffer) {
for (size_t i = 0; i<N; i++) {
if (buffer[i]) Note_NonZeroValue();
}
}
// Clean-up when done.
free(buffer);
buffer = 0;
The tricky thing about C is that even if char does not have a trap value, some smart compiler could identify code is attempting something that is UB per the spec and then optimize if (buffer[0]) into nothing. Reading uninitialized non-unsigned char data is a no-no.

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.

How to allocate memory for an array of strings of unknown length in C

I have an array, say, text, that contains strings read in by another function. The length of the strings is unknown and the amount of them is unknown as well. How should I try to allocate memory to an array of strings (and not to the strings themselves, which already exist as separate arrays)?
What I have set up right now seems to read the strings just fine, and seems to do the post-processing I want done correctly (I tried this with a static array). However, when I try to printf the elements of text, I get a segmentation fault. To be more precise, I get a segmentation fault when I try to print out specific elements of text, such as text[3] or text[5]. I assume this means that I'm allocating memory to text incorrectly and all the strings read are not saved to text correctly?
So far I've tried different approaches, such as allocating a set amount of some size_t=k , k*sizeof(char) at first, and then reallocating more memory (with realloc k*sizeof(char)) if cnt == (k-2), where cnt is the index of **text.
I tried to search for this, but the only similar problem I found was with a set amount of strings of unknown length.
I'd like to figure out as much as I can on my own, and didn't post the actual code because of that. However, if none of this makes any sense, I'll post it.
EDIT: Here's the code
int main(void){
char **text;
size_t k=100;
size_t cnt=1;
int ch;
size_t lng;
text=malloc(k*sizeof(char));
printf("Input:\n");
while(1) {
ch = getchar();
if (ch == EOF) {
text[cnt++]='\0';
break;
}
if (cnt == k - 2) {
k *= 2;
text = realloc(text, (k * sizeof(char))); /* I guess at least this is incorrect?*/
}
text[cnt]=readInput(ch); /* read(ch) just reads the line*/
lng=strlen(text[cnt]);
printf("%d,%d\n",lng,cnt);
cnt++;
}
text=realloc(text,cnt*sizeof(char));
print(text); /*prints all the lines*/
return 0;
}
The short answer is you can't directly allocate the memory unless you know how much to allocate.
However, there are various ways of determining how much you need to allocate.
There are two aspects to this. One is knowing how many strings you need to handle. There must be some defined way of knowing; either you're given a count, or there some specific pointer value (usually NULL) that tells you when you've reached the end.
To allocate the array of pointers to pointers, it is probably simplest to count the number of necessary pointers, and then allocate the space. Assuming a null terminated list:
size_t i;
for (i = 0; list[i] != NULL; i++)
;
char **space = malloc(i * sizeof(*space));
...error check allocation...
For each string, you can use strdup(); you assume that the strings are well-formed and hence null terminated. Or you can write your own analogue of strdup().
for (i = 0; list[i] != NULL; i++)
{
space[i] = strdup(list[i]);
...error check allocation...
}
An alternative approach scans the list of pointers once, but uses malloc() and realloc() multiple times. This is probably slower overall.
If you can't reliably tell when the list of strings ends or when the strings themselves end, you are hosed. Completely and utterly hosed.
C don't have strings. It just has pointers to (conventionally null-terminated) sequence of characters, and call them strings.
So just allocate first an array of pointers:
size_t nbelem= 10; /// number of elements
char **arr = calloc(nbelem, sizeof(char*));
You really want calloc because you really want that array to be cleared, so each pointer there is NULL. Of course, you test that calloc succeeded:
if (!arr) perror("calloc failed"), exit(EXIT_FAILURE);
At last, you fill some of the elements of the array:
arr[0] = "hello";
arr[1] = strdup("world");
(Don't forget to free the result of strdup and the result of calloc).
You could grow your array with realloc (but I don't advise doing that, because when realloc fails you could have lost your data). You could simply grow it by allocating a bigger copy, copy it inside, and redefine the pointer, e.g.
{ size_t newnbelem = 3*nbelem/2+10;
char**oldarr = arr;
char**newarr = calloc(newnbelem, sizeof(char*));
if (!newarr) perror("bigger calloc"), exit(EXIT_FAILURE);
memcpy (newarr, oldarr, sizeof(char*)*nbelem);
free (oldarr);
arr = newarr;
}
Don't forget to compile with gcc -Wall -g on Linux (improve your code till no warnings are given), and learn how to use the gdb debugger and the valgrind memory leak detector.
In c you can not allocate an array of string directly. You should stick with pointer to char array to use it as array of string. So use
char* strarr[length];
And to mentain the array of characters
You may take the approach somewhat like this:
Allocate a block of memory through a call to malloc()
Keep track of the size of input
When ever you need a increament in buffer size call realloc(ptr,size)

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