As others have said, you have to tell malloc
how much memory you want. Note that if you don't allocate enough memory initially, you can use realloc
to request more memory.
Here's an example. Suppose you want to store a line of text (delimited by a newline) from an input stream, but you don't know how long the line is, so you don't know ahead of time how much memory to allocate. You can read the input stream piecemeal into a smaller fixed-size buffer, and append that to a dynamic buffer that you can resize as necessary:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
/**
* Reads a line of text (delimited by a newline character) from an
* input stream into a dynamic buffer.
*/
char *getNextLine(FILE *stream, size_t *lineSize)
{
char inbuf[SIZE]; // fixed-size input buffer
char *line = NULL; // points to our dynamic buffer
char *newline = NULL;
char *(*append)(char *, const char *) = strcpy;
*lineSize = 0;
/**
* Read from the input stream until we see a newline character
* or the read fails (EOF or error).
*/
while (!newline && fgets(inbuf, sizeof inbuf, stream))
{
/**
* Resize the buffer to accomodate the string in the input buffer
* (allocates the buffer the first time through).
*/
char *tmp = realloc(line, *lineSize + strlen(inbuf) + 1);
if (tmp)
{
/**
* Check for a newline in the input buffer
*/
newline = strchr(inbuf, '\n');
/**
* If present, overwrite the newline with a 0 (nul terminator
* character). If you want to keep the newline in the target
* buffer, skip this step.
*/
if (newline)
*newline = 0;
/**
* Assign the temporary variable back to line and update the
* output buffer size.
*/
line = tmp;
*lineSize += strlen(inbuf) + 1;
/**
* Write the contents of the input buffer to the target buffer.
* First time through the loop we'll use strcpy (called through
* the append function pointer); on each successive iteration
* we'll use strcat to append the contents of the input buffer
* to the target buffer.
*/
append(line, inbuf);
append = strcat;
}
else
{
/**
* The realloc function failed; at this point, we'll just return
* what we have.
*/
printf("Unable to extend buffer\n");
}
}
if (!newline && !feof(stream))
{
printf("Error on read!\n");
}
return line;
}
This code uses realloc
instead of malloc
for the initial allocation (calling realloc
with NULL as the first argument is the same as calling malloc
).
Note that we assign the result of realloc
to a temporary variable. If realloc
fails (there isn't enough memory to satisfy the request) it will return NULL; if we assigned this to line
we'd lose our pointer to any memory we've already allocated, causing a memory leak.
There's a little trickery with the append
function pointer. The first time through the loop we want to copy our input buffer to the target buffer, so we set append
to point to strcpy
. After that, we want to append what's in the input buffer to the contents of the target buffer, so we set append
to point to strcat
.
Note that it's up to the caller to free the dynamic buffer when it's done with it.