C Memory leaks with char ** - c

i was playing arround with the C malloc and free tools and i had a weird memory leak. Does someone has an idea about it?
The goal is to successfully free a char**.
So in the function freezer, i free every char* in the char** and the i free the char**.
But Valgrind (my leaks detector on linux) find 20 bytes in 4 blocks leaked (i don't know if i can write 'leaked' XD)
The more interesting part is that if i do a bigger char** by adding a char* in it, it leak 5 more bytes of memory in another block :/.
#include <stdio.h>
#include <stdlib.h>
void freezer(char ***array, int length){
int i;
i = -1;
while (*array[++i] != NULL){
free(*array[i]);
}
free(*array);
}
int main(){
char **big;
int len = 4;
int i;
big = malloc(sizeof(char *) * (len + 1));
i = -1;
while (++i < len){
big[i] = malloc(sizeof(char) * 5);
big[i][0] = 't';
big[i][1] = 'e';
big[i][2] = 's';
big[i][3] = 't';
big[i][4] = '\0';
}
big[i] = NULL;
i = -1;
while (++i < len){
printf("i: %d\t%s\n", i, big[i]);
}
freezer(&big, len);
return (0);
}
You can directly copy/past/run the code as it is.
So if you have any clue about the error/C problem, please let me know.

big[i] = NULL; causes a buffer overflow. You only allocated space for a total of len entries, plus one byte; but at that point i == len.
Perhaps you meant big = malloc(sizeof(char *) * (len + 1));
Also, the freezer function dereferences and frees the wrong thing. Either change it to accept char **array , or replace all occurrences of array with (*array) inside the function. The former is preferable, there is no need to pass by reference in order to call free.
Your loop structure is weird for no apparent reason; it's normal to use:
for (i = 0; i < len; ++i)
which is the same logic but will make your code easier to digest for people reading it.
Also, don't cast malloc

Related

C - Using malloc, realloc and free. I get too many memory leaks, what's wrong?

So, my goal was to define a struct in which there is -
A command name (e.g. - "print")
Command arguments counter
A strings array containing the arguments.
You can review my code, but I'm really having a hard time understanding what am I doing wrong -
I use malloc to dynamically set my_struct.command size
I use malloc to dynamically set my_struct.arguments array size
I use realloc to dynamically increase my_struct.arguments size for every argument I set
I use malloc to dynamically set my_struct.arguments[i] size
I finally call cleanup(), to free any dynamically assigned pointers.
I keep getting LOTS of memory leaks. But I cannot understand why.
Help and tips will be kindly appreciated.
#include <stdio.h>
#include <stdlib.h>
struct {
char *command;
int arguments_count;
char **arguments;
} my_struct;
void cleanup(void);
int main() {
int i;
my_struct.command = (char *)malloc(6*sizeof(char));
my_struct.command = "print";
my_struct.arguments_count = 1;
my_struct.arguments = (char **)malloc(sizeof(char *));
my_struct.arguments[0] = "hello";
for(i = 1 ; i < 10; i++) {
my_struct.arguments = (char **)realloc(my_struct.arguments, sizeof(char *)*(i+1));
my_struct.arguments[i] = (char *)malloc(8*sizeof(char));
my_struct.arguments[i] = "hello";
my_struct.arguments_count++;
}
printf("Arguments count is: %d\n", my_struct.arguments_count);
printf("The arguments are:\n");
for(i = 0; i < 10; i++) {
printf("%s\n", my_struct.arguments[i]);
}
cleanup();
exit(0);
}
void cleanup(void) {
int i;
for(i = 0; i < 10; i++)
free(my_struct.arguments[i]);
free(my_struct.arguments);
free(my_struct.command);
}
strdup - The strdup() function returns a pointer to a new
string which is a duplicate of the string s. Memory for the new
string is obtained with malloc, and can be freed with free.
my_struct.command = strdup("print");
my_struct.arguments_count = 1;
my_struct.arguments = (char**) malloc(sizeof(char*));
my_struct.arguments[0] = strdup("hello");
for (int i=1; i < 10; ++i) {
// if the number of args is known, allocate before entering the loop
my_struct.arguments = (char**) realloc(my_struct.arguments, sizeof(char*)*(i+1));
my_struct.arguments[i] = strdup("hello");
my_struct.arguments_count++;
}
// in your cleanup use the arguments_count var instead of the literal 10
for (int i=0; i < my_struct.arguments_count; ++i)
Your mistake was:
// allocate a memory block of 6 bytes
// assign the address of that block to command
my_struct.command = malloc(6);
// then you assigned the address of the string 'print' to command
// therefore the previous allocated block is lost -> mem leak
my_struct.command = "print";
// strdup does the following
return memcpy(malloc(strlen(str) + 1), str, strlen(str) + 1);

how to malloc memory for string pointers array, and other problems

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_SIZE 100
#define INITIAL_BUFFER_SIZE 16
int main() {
char **line_buffer;
line_buffer = (char **) malloc(INITIAL_BUFFER_SIZE);
int i = 0;
int lines = 0;
// the size of buffer
int buffer_size = 1;
int *buffer_size_p = &buffer_size;
char *line_one = (char *) malloc(MAX_LINE_SIZE);
//read lines from a file
while (gets(line_one)) {
line_buffer[lines] = (char *) malloc(MAX_LINE_SIZE);
strcpy(line_buffer[lines], line_one);
lines++;
line_one = (char *) malloc(MAX_LINE_SIZE);
// if too much lines double the buffer size
if (lines == *buffer_size_p) {
buffer_size *= 2;
line_buffer = IncreaseBuffer(line_buffer, buffer_size_p);
}
}
PrintLines(line_buffer, lines);
// sorting all the line by strcmp
for (i = 0; i < lines; i++) {
printf("%s", line_buffer[i]);
// int min = MinLineIndex(line_buffer, i, lines);
// SwapLines(line_buffer, i, min);
}
PrintLines(line_buffer, lines);
// free(line_buffer);
return 0;
}
First, ignore the gets() function, this is required for this.
First, I used a for loop to do (char *) line_buffer[lines] = (char *) malloc(MAX_LINE_SIZE);
It does not work;
I did this way, it worked, However, after read several lines from a file, the first line become something like "��R", and it is changing every time.
And, I cannot use free(line_buffer); as well.
Self studying. Please help.
A big problem is that you only allocate 16 bytes for line_buffer, which on a 64-bit system would mean you only allocate space for two pointers.
If you read more than two (or four on 32-bit systems) lines you will go out of bounds.
If you want to allocate space for 16 pointers, then you need to allocate space for INITIAL_BUFFER_SIZE * sizeof(char *) bytes, or better yet, INITIAL_BUFFER_SIZE * sizeof(*line_buffer).
Then there's the issue of memory leaks, of which you have quite a few. First of all you don't need to allocate memory for the temporary buffer line_one, declare it as a normal fixed-size array. That will get rid of quite a few leaks as you reallocate it in the loop without freeing the old memory.
Then to free the line_buffer memory you actually need to free each individual entry first, before you call free on line_buffer.
Remember: For each malloc you need a corresponding free.
And instead of allocating and copying each line explicitly, while it's not a standard C function just about all libraries have a strdup function which does it for you, so you can do e.g.
line_buffer[lines] = strdup(line_one);
And the buffer_size_p variable is not needed, if you need to use a pointer to the buffer_size variable, just use the address-of operator directly when needed, like in
line_buffer = IncreaseBuffer(line_buffer, &buffer_size);
From what you've posted your use (or, rather incorrect) use malloc may be the culprit.
For line buffer, you are only allocating 16 bytes, when really you should have been doing this:
line_buffer = (char **) malloc(INITIAL_BUFFER_SIZE*sizeof(char*));
Also, I would also encourage the use of sizeof in your other malloc call:
line_buffer[lines] = (char *) malloc(MAX_LINE_SIZE*sizeof(char))
The next crucial thing is:
int buffer_size = 1;
should be:
int buffer_size = INITIAL_BUFFER_SIZE;
After, all, you just allocated INITIAL_BUFFER_SIZE pointers to lines.
(Posted on behalf of the OP).
First, ignore the gets() function, this is required for this:
(char **) malloc(INITIAL_BUFFER_SIZE * sizeof(char *))
Almost all the problems are because I don't know I need to use * sizeof(char *).
Here is my final code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_SIZE 100
#define INITIAL_BUFFER_SIZE 16
int main() {
char **line_buffer;
line_buffer = (char **) malloc(INITIAL_BUFFER_SIZE * sizeof(char *));
int i = 0;
int lines = 0;
for (i = 0; i<INITIAL_BUFFER_SIZE; i++){
line_buffer[i] = (char *) malloc(MAX_LINE_SIZE * sizeof(char));
}
// the size of buffer
int buffer_size = INITIAL_BUFFER_SIZE;
while (gets(line_buffer[lines++])) {
if (lines == buffer_size) {
buffer_size *= 2;
line_buffer = IncreaseBuffer(line_buffer, &buffer_size);
}
}
// sorting all the line by strcmp
for (i = 0; i < lines; i++) {
int min = MinLineIndex(line_buffer, i, lines - 2);
SwapLines(line_buffer, i, min);
}
PrintLines(line_buffer, lines - 1);
for (i = 0; i < buffer_size ; i++) {
free(line_buffer[i]);
}
free(line_buffer);
return 0;
}

Manipulating dynamic arrays in C

I am trying to solve StringMerge (PP0504B) problem from SPOJ (PL). Basically the problem is to write a function string_merge(char *a, char *b) that returns a pointer to an char array with string created from char arrays with subsequent chars chosen alternately (length of the array is the length of the shorter array provided as an argument).
The program I've created works well with test cases but it fails when I post it to SPOJ's judge. I'm posting my code here, as I believe it the problem is related to memory allocation (I'm still learning this part of C) - could you take a look at my code?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define T_SIZE 1001
char* string_merge(char *a, char *b);
char* string_merge(char *a, char *b) {
int alen = strlen(a); int blen = strlen(b);
int len = (alen <= blen) ? alen : blen;
int i,j;
char *new_array = malloc (sizeof (char) * (len));
new_array[len] = '\0';
for(j=0,i=0;i<len;i++) {
new_array[j++] = a[i];
new_array[j++] = b[i];
}
return new_array;
}
int main() {
int n,c; scanf("%d", &n);
char word_a[T_SIZE];
char word_b[T_SIZE];
while(n--) {
scanf("%s %s", word_a, word_b);
char *x = string_merge(word_a, word_b);
printf("%s",x);
printf("\n");
memset(word_a, 0, T_SIZE);
memset(word_b, 0, T_SIZE);
memset(x,0,T_SIZE);
}
return 0;
}
Note: I'm compiling it with -std=c99 flag.
Off-by-one.
char *new_array = malloc (sizeof (char) * (len));
new_array[len] = '\0';
You're writing past the bounds of new_array. You must allocate space for len + 1 bytes:
char *new_array = malloc(len + 1);
Also, sizeof(char) is always 1, so spelling it out is superfluous, so are the parenthesis around len.
Woot, further errors!
So then you keep going and increment j twice within each iteration of the for loop. So essentially you end up writing (approximately) twice as many characters as you allocated space for.
Also, you're leaking memory by not free()ing the return value of string_merge() after use.
Furthermore, I don't see what the memsets are for, also I suggest you use fgets() and strtok_r() for getting the two words instead of scanf() (which doesn't do what you think it does).
char *new_array = malloc (sizeof (char) * (len*2 + 1));
new_array[len*2] = '\0';

pointer freed not allocated

when I compile this piece of code, the pointer freed not allocated error pops up. Could someone please explain why that is? Thank you!
static int make_buffer(FILE *input, char *buffer[]){
*buffer = (char *)malloc(INIT_BUFFER_SIZE*sizeof(char));
int buffer_size = INIT_BUFFER_SIZE;
int txt_size = 0;
char cha;
while((cha = fgetc(input)) != EOF){
if (txt_size == buffer_size){
*buffer = (char *)realloc(buffer, buffer_size*2*sizeof(char));
buffer_size *= 2;
}
(*buffer)[txt_size] = cha;
txt_size ++;
}
free(*buffer);
return txt_size;
}
It means that the code is attempting to free something that was not allocated using malloc/realloc. In your case, I think the problem is in
*buffer = (char *)realloc(buffer, buffer_size*2*sizeof(char));
which should be
*buffer = realloc(*buffer, buffer_size*2);
Probably also want to check the result of realloc just for form. Note I simplified yours a bit in that sizeof(char) == 1 by definition and the cast shouldn't be needed these days (it used to be). The commend by David S. about the usefulness of freeing the result is also valid.

C: creating array of strings from delimited source string

What would be an efficient way of converting a delimited string into an array of strings in C (not C++)? For example, I might have:
char *input = "valgrind --leak-check=yes --track-origins=yes ./a.out"
The source string will always have only a single space as the delimiter. And I would like a malloc'ed array of malloc'ed strings char *myarray[] such that:
myarray[0]=="valgrind"
myarray[1]=="--leak-check=yes"
...
Edit I have to assume that there are an arbitrary number of tokens in the inputString so I can't just limit it to 10 or something.
I've attempted a messy solution with strtok and a linked list I've implemented, but valgrind complained so much that I gave up.
(If you're wondering, this is for a basic Unix shell I'm trying to write.)
What's about something like:
char* string = "valgrind --leak-check=yes --track-origins=yes ./a.out";
char** args = (char**)malloc(MAX_ARGS*sizeof(char*));
memset(args, 0, sizeof(char*)*MAX_ARGS);
char* curToken = strtok(string, " \t");
for (int i = 0; curToken != NULL; ++i)
{
args[i] = strdup(curToken);
curToken = strtok(NULL, " \t");
}
if you have all of the input in input to begin with then you can never have more tokens than strlen(input). If you don't allow "" as a token, then you can never have more than strlen(input)/2 tokens. So unless input is huge you can safely write.
char ** myarray = malloc( (strlen(input)/2) * sizeof(char*) );
int NumActualTokens = 0;
while (char * pToken = get_token_copy(input))
{
myarray[++NumActualTokens] = pToken;
input = skip_token(input);
}
char ** myarray = (char**) realloc(myarray, NumActualTokens * sizeof(char*));
As a further optimization, you can keep input around and just replace spaces with \0 and put pointers into the input buffer into myarray[]. No need for a separate malloc for each token unless for some reason you need to free them individually.
Were you remembering to malloc an extra byte for the terminating null that marks the end of string?
From the strsep(3) manpage on OSX:
char **ap, *argv[10], *inputstring;
for (ap = argv; (*ap = strsep(&inputstring, " \t")) != NULL;)
if (**ap != '\0')
if (++ap >= &argv[10])
break;
Edited for arbitrary # of tokens:
char **ap, **argv, *inputstring;
int arglen = 10;
argv = calloc(arglen, sizeof(char*));
for (ap = argv; (*ap = strsep(&inputstring, " \t")) != NULL;)
if (**ap != '\0')
if (++ap >= &argv[arglen])
{
arglen += 10;
argv = realloc(argv, arglen);
ap = &argv[arglen-10];
}
Or something close to that. The above may not work, but if not it's not far off. Building a linked list would be more efficient than continually calling realloc, but that's really besides the point - the point is how best to make use of strsep.
Looking at the other answers, for a beginner in C, it would look complex due to the tight size of code, I thought I would put this in for a beginner, it might be easier to actually parse the string instead of using strtok...something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
char **parseInput(const char *str, int *nLen);
void resizeptr(char ***, int nLen);
int main(int argc, char **argv){
int maxLen = 0;
int i = 0;
char **ptr = NULL;
char *str = "valgrind --leak-check=yes --track-origins=yes ./a.out";
ptr = parseInput(str, &maxLen);
if (!ptr) printf("Error!\n");
else{
for (i = 0; i < maxLen; i++) printf("%s\n", ptr[i]);
}
for (i = 0; i < maxLen; i++) free(ptr[i]);
free(ptr);
return 0;
}
char **parseInput(const char *str, int *Index){
char **pStr = NULL;
char *ptr = (char *)str;
int charPos = 0, indx = 0;
while (ptr++ && *ptr){
if (!isspace(*ptr) && *ptr) charPos++;
else{
resizeptr(&ptr, ++indx);
pStr[indx-1] = (char *)malloc(((charPos+1) * sizeof(char))+1);
if (!pStr[indx-1]) return NULL;
strncpy(pStr[indx-1], ptr - (charPos+1), charPos+1);
pStr[indx-1][charPos+1]='\0';
charPos = 0;
}
}
if (charPos > 0){
resizeptr(&pStr, ++indx);
pStr[indx-1] = (char *)malloc(((charPos+1) * sizeof(char))+1);
if (!pStr[indx-1]) return NULL;
strncpy(pStr[indx-1], ptr - (charPos+1), charPos+1);
pStr[indx-1][charPos+1]='\0';
}
*Index = indx;
return (char **)pStr;
}
void resizeptr(char ***ptr, int nLen){
if (*(ptr) == (char **)NULL){
*(ptr) = (char **)malloc(nLen * sizeof(char*));
if (!*(ptr)) perror("error!");
}else{
char **tmp = (char **)realloc(*(ptr),nLen);
if (!tmp) perror("error!");
*(ptr) = tmp;
}
}
I slightly modified the code to make it easier. The only string function that I used was strncpy..sure it is a bit long-winded but it does reallocate the array of strings dynamically instead of using a hard-coded MAX_ARGS, which means that the double pointer is already hogging up memory when only 3 or 4 would do, also which would make the memory usage efficient and tiny, by using realloc, the simple parsing is covered by employing isspace, as it iterates using the pointer. When a space is encountered, it reallocates the double pointer, and malloc the offset to hold the string.
Notice how the triple pointers are used in the resizeptr function.. in fact, I thought this would serve an excellent example of a simple C program, pointers, realloc, malloc, passing-by-reference, basic element of parsing a string...
Hope this helps,
Best regards,
Tom.

Resources