Memory leak after using calloc and free? - c

I tested my software with "valgrind --leak-check=full", and it shows:
==90862== 7,627 bytes in 4 blocks are definitely lost in loss record 858 of 897
==90862== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==90862== by 0xD64991C: concat(int, ...) (Client.cpp:150)
I can't understand why, because I use free() after calloc.
Here's my code:
char* p = concat(2, buffOld, buff);
char *x;
while(true) {
x = p;
p = strstr(p,"\\final\\");
if(p == NULL) { break; }
*p = 0;
p+=7;
parseIncoming((char *)x,strlen(x));
}
free(p);
And the "concat" function:
char* concat(int count, ...)
{
va_list ap;
int i;
// Find required length to store merged string
int len = 1; // room for NULL
va_start(ap, count);
for(i=0 ; i<count ; i++)
len += strlen(va_arg(ap, char*));
va_end(ap);
// Allocate memory to concat strings
char *merged = (char*)calloc(sizeof(char),len);
int null_pos = 0;
// Actually concatenate strings
va_start(ap, count);
for(i=0 ; i<count ; i++)
{
char *s = va_arg(ap, char*);
strcpy(merged+null_pos, s);
null_pos += strlen(s);
}
va_end(ap);
return merged;
}
What I do wrong?

I can't understand why, because I use free() after calloc
Yes, but (if I understand correctly) you free() the wrong pointer.
You should copy p in another pointer (before modifing it) and free() the save copy.
Look at your code
char* p = concat(2, buffOld, buff);
char *x;
while(true) {
x = p;
p = strstr(p,"\\final\\");
if(p == NULL) { break; }
*p = 0;
p+=7;
parseIncoming((char *)x,strlen(x));
}
free(p);
The pointer p is initialized with the calloc-ed pointer but the while cicle modify it and return only when p is NULL.
So, when you call
free(p)
you're calling
free(nullptr)
--- EDIT ---
I still don't understand it. I added free(x) at the end, and it crashes
My initial suggestion to free(x) was a mistake of mine because I didn't pointed the attention to the fact that x is initializes with the p value but is modified in the while loop. Thanks again to Johnny Mopp for pointing my attention to it.
I suggest the use of another variable to memorize the original value of p (the exact value returned by calloc()) and free this value.
Something like
char* p = concat(2, buffOld, buff);
char *x;
char * const forFree = p; /* <--- saving calloc() returned value */
while(true) {
x = p;
p = strstr(p,"\\final\\");
if(p == NULL) { break; }
*p = 0;
p+=7;
parseIncoming((char *)x,strlen(x));
}
free(forFree);

Related

How can I free an array of pointers where each pointer points to an address of a string which I allocated inside of a function?

How can I free an array of pointers where each pointer points to an address of a string which I allocated inside of a function?
I created a simple array of pointers, *pointers[], inside my main and I'm passing it to readline which returns the amount of lines I have read.
The purpose of this is to store all the lines of the input separated by '\n'. Each line is stored in a pointer in the array of pointers.
So after readline is called and it returns, I can printf("%s", pointers[0]) which will show the first line the user typed in.
The way I assign a line to each pointer in my array is inside readline by allocating a char pointer, *p, to have MAXLENGTH sizes and passing the current address of p to the respective pointer. After each assignment is done, I jump to the next free address of p.
Finally, my question is if I have to free (and how) my array of pointers after the readline routine is complete and I have printed all the lines stored.
I'll leave the two functions, main and readline, here for you.
#define NUMOFLINES 5
#define MAXLENGTH 1000
void main(void) {
char *pointers[NUMOFLINES]; // Array of pointers to string
int nlines; // Number of pointers read
nlines = readlines(pointers);
writelines(pointers, nlines);
/* FAILED ATTEMPT TO FREE THE ARRAY OF POINTERS */
for(int i = 0 ; i < nlines ; i++)
free(pointers[i]);
}
int readlines(char *pointers[]) {
char line[MAXLENGTH];
char *p;
int iptr, len;
/* ALLOCATE P */
p = malloc(sizeof(char) * MAXLENGTH);
for(iptr = 0 ; iptr < NUMOFLINES && (len = get_line(line)) > 0 ; iptr++)
{
strcpy(p, line); // copy the line to the array, ending in len-th position
pointers[iptr] = p; // Pass current adress 'p' to the respectively index of pointers
p += len+1; // Next free adress in array p
}
return iptr;
}
As you can see I tried to free by going through each pointer and calling free(pointer[i], but all I get is
malloc(): corrupted top size
Aborted (core dumped)
Do I need to call free?
Thanks in advance.
You are calling malloc() only 1 time, but you are calling free() multiple times. Every char* in your array points within that single malloc()'ed memory block. You can only call free() 1 time on the starting address of that block. Calling free() on addresses inside the block is undefined behavior.
Also, the memory block you are allocating with malloc() is not nearly large enough, assuming each string that get_line() outputs can be up to MAXLENGTH characters. You are only allocating enough memory for the maximum length of 1 single line, so as soon as your reading loop has copied MAXLENGTH characters into the allocated block, you are advancing your p pointer beyond the bounds of the block, causing subsequent strcpy()'s to write into and corrupt random memory.
If you want to stay with a single malloc() and sub-divide it, try something more like this instead:
#define NUMOFLINES 5
#define MAXLENGTH 1000
int main(void) {
char *pointers[NUMOFLINES], *buffer;
int nlines = readlines(pointers, &buffer);
if (nlines < 0) return -1;
writelines(pointers, nlines);
free(buffer);
return 0;
}
int readlines(char *pointers[], char **buffer) {
*buffer = malloc(sizeof(char) * (NUMOFLINES * MAXLENGTH));
if (*buffer == NULL) return -1;
int iptr, len;
char *p = *buffer;
for(iptr = 0; (iptr < NUMOFLINES) && ((len = get_line(p)) > 0); ++iptr)
{
pointers[iptr] = p;
p += len + 1;
}
return iptr;
}
Otherwise, I suggest you allocate a separate buffer for each pointer in the array, eg:
#define NUMOFLINES 5
#define MAXLENGTH 1000
int main(void) {
char *pointers[NUMOFLINES];
int nlines = readlines(pointers);
if (nlines < 0) return -1;
writelines(pointers, nlines);
for(int i = 0; i < nlines; ++i)
free(pointers[i]);
return 0;
}
int readlines(char *pointers[]) {
char line[MAXLENGTH], *p;
int iptr, len;
for(iptr = 0; (iptr < NUMOFLINES) && ((len = get_line(line)) > 0); ++iptr)
{
p = malloc(sizeof(char) * (len + 1));
if (p == NULL) {
for(int j = 0; j < iptr; ++j) free(pointers[j]);
return -1;
}
memcpy(p, line, sizeof(char) * len);
p[len] = '\0';
pointers[iptr] = p;
}
return iptr;
}
You only call malloc once, so you should only call free once.
After readlines returns, pointers[0] points to the start of the memory you allocated, while the remaining array members point someplace within that same block of memory. That means there's only one pointer to free.
So instead of this:
for(int i = 0 ; i < nlines ; i++)
free(pointers[i]);
Just do this:
free(pointers[0]);
To reiterate, you should only pass to free a pointer value that was returned from malloc (or realloc or calloc).
You don't need to free the other pointers you maintain within your buffer. If you do a single
p = malloc(sizeof(char) * MAXLENGTH);
then you need a single
free(p);
The malloc and free have to match exactly 1-to-1 and be called with the same addresses.
Since you want to modify p, you should do:
char* original = malloc(sizeof(char) * MAXLENGTH);
p = original;
and, once done:
free(original)

array value not updating

I have a strtok implementation (sort of), but it doesn't print the token!
char *tokenizer(char s[], const char *delimiter) {
char *p; //return value of function
int i = 0;
while(s[i] != *delimiter) //to get the size of array just right
i++;
char arr[i+1];
p = arr; //can't return an array, so assigned to a
//pointer
int j = 0;
i = 0;
while(s[i]!=*delimiter) {
arr[j] = s[i];
i++;
j++;
}
arr[j] = '\0';
printf("%s\n",p); //this statement works, but if excluded
//main prints nothing.
return p;
}
This function is being called as following, from the main:
char s[] = "tab-tab";
const char del[2] = "-";
char *p;
p = tokenizer(s, del);
printf("%s\n", p); //prints nothing without the printf in
//tokenizer
I tried debugging with gdb, and inspected the values of local variable after each line. p is updated with arr[j] inside tokenizer but goes to zero as soon as tokenizer finishes and frame shifts back to main.
The value ofp in main doesn't become NULL, it becomes an empty string, and prints that!
However, p in main prints the token if printf in tokenizer is included.
This already includes work-around. I know this can't possibly be the way strtok is implemented. I started with a more sophisticated, "expertish" version which had pointers, but couldn't get it to work, so settled for this "beginner" version.
It's because your pointer is pointing to a memory address in the stack, once your function is returned the memory address being pointed to no longer exists, you need to create dynamically allocated memory to access the variable outside of the function. The beauty of C
char *tokenizer(char s[], const char *delimiter) {
char *arr;
int i = 0;
while(s[i] != *delimiter)
i++;
// Initialize variable in the heap
if (!(arr = malloc(sizeof(char *) * (i+1))))
return NULL;
// Clear the array
bzero(arr, (i+1));
int j = 0;
i = 0;
while(s[i]!=*delimiter) {
arr[j] = s[i];
i++;
j++;
}
arr[j] = '\0';
// return pointer
return arr;
}
You should make sure to free the memory in the main to prevent memory leaks.

Converting old C code

I have this code snippet in project source code which I work on
void func(void **p,size_t s)
{
*p = malloc(s+sizeof(size_t));
*(((size_t *)(*p))++) = s;
}
and gcc-4.7 does not compile it. gcc returns
lvalue required as increment operand
error message. I changed it into
stp = ((size_t *)(*p));
*(stp ++) = s;
and
stp = ((size_t *)(*p));
*stp = *stp + 1;
*stp = s;
gcc compiles both of them. But application does not work expected.
Is conversion true? And is there any tool for conversion?
The idea seems to be to allocate a certain amount of memory (s) and an additional amount to store this size allocated in the same area as a leading block and then return a pointer to just behind the stored size.
So try this:
void func(void ** p, size_t s)
{
size_t * sp = malloc(s + sizeof s);
if (NULL != sp)
{
*sp = s;
++sp;
}
*p = sp;
}
Btw, freeing the allocated memory, is not straight forward.
A typicall sequence of calls, also freeing what this function returns, would look like this then:
void * pv = NULL;
func(&pv, 42);
if (NULL != pv)
{
/* Use 42 bytes of memory pointed to by pv here. */
free(((char *) pv) - sizeof (size_t));
}
*(((size_t *)(*p))++) = s;
Breakdown:
*(
(
(size_t *) (*p)
) ++
) = s
Means : Take *p as a pointer to size_t (let's call that ptr for after), dereference it (= take the size_t typed value at the address *p), assign that value to s and finally increment ptr (which is to say increment the address in *p by the sizeof(size_t).
You can translate that to:
size_t *ptr = (size_t*)(*p); //second pair of paren is optionnal
s = *ptr;
ptr = ptr + 1; //Warning: This will only modify the variable ptr and not
//the data at its original place *p, if the remainder of
//the program is based on that (which I highly suspect)
//you should do instead :
(size_t*)*p = (size_t*)(*p) + 1; //This also ensures "+1" is treated as
//"add the sizeof(size_t)" because *p
//points to a size_t typed variable
You could also retype a variable and have it point at the same location as p and be done with the casts:
void func(void **p,size_t s)
{
size_t **ptr = p;
*ptr = malloc(s+sizeof(size_t));
if (*ptr == NULL) etc...
*((*ptr)++) = s;
}
func2() : Adding a variable can increase readability, IMHO. (and inlining will get rid of it, afterwards)
The second function func3() demonstrates that using the return value instead of passing a (opaque) pointer by reference can avoid complexity and casts
#include <stdio.h>
#include <stdlib.h>
void func2(void **p,size_t s)
{
size_t **pp;
pp = (size_t **) p; // only one cast
*pp = malloc(s+sizeof(size_t));
if (!*pp) return;
fprintf(stderr,"[mallocd %p]", *pp);
*pp[0] = s;
*pp += 1;
}
void *func3(size_t s)
{
size_t *p;
p = malloc(s+sizeof *p);
if (!p) return NULL;
fprintf(stderr,"[mallocd %p]", p);
p[0] = s;
return p+1;
}
int main(void)
{
char *p = NULL , *p2 = NULL;
func2( (void**) &p, 666); // yet another cast
fprintf(stderr,"returned p := %p\n", p);
p2 = func3( 666); // No cast!!!
fprintf(stderr,"returned p2 := %p\n", p2);
return 0;
}
try
void func(void **p,size_t s)
{
*p = malloc(s+sizeof(size_t));
*(*(size_t **)p)++ = s;
}
This is allocating s bytes of memory, plus enough extra to hold s, storing s at the start of that space and modifying *p to point just after that.
More sensible and clearer (and avoiding casts!) would be:
void *func(size_t s)
{
size_t *p = malloc(s + sizeof(size_t));
if (p) *p++ = s;
return p;
}
but that requires changing the code that calls this function to take the return value and store it wherever desired, rather than passing an extra pointer as an argument:
some_ptr = func(needed_size);
rather than
func((void **)&some_ptr, needed_size);
also avoiding casts...

Returning char* to print in C

So I am trying to print out a char* array after being returned from a function but I keep getting a segfault.
char* return(node *n){
node* p = list->head;
int count = 0;
int size = 0;
while(p != NULL){
size += strlen(p->name);
count++;
p = p->nxt;
}
size = size + 1; // for the '\0'
char * arr[count][size];
p = list->head;
count = 0;
while(p != NULL){
strcpy(arr[count], p->name);
count++;
p = p->next;
}
return arr;
}
I then go to try and print it out in my main method on a certain node. and I get a segmentation fault.
char* test = return(node1);
for(i = 0; i < 5; i++){
printf("%s", test[i]);
}
Your arr is local to the (unfortunately named) function. When the function exits, the space is deallocated. If you use that pointer afterwards, you are indexing into unknown, and most likely somewhere you're not supposed to (which results in a segfault).
When you want to allocate space in a function and return a pointer, you should use malloc (or equivalent), and remember to free the space afterwards. An alternate way is to have the pointer be a parameter to the function, and leave the reponsibility for allocation (and deallocation) to the caller (like fgets does).
Approach 1 (allocation inside the function):
char *foo() {
char *arr = malloc(100);
return arr;
}
/* somewhere else */
char *arr = foo();
/* use arr */
free(arr);
Approach 2 (allocation outside the function):
void foo(char *arr, size_t size) {
/* do stuff to arr */
}
/* somewhere else */
char *arr = char[100];
foo(arr, 100);
EDIT: Was wrong. Ignore what was here.

realloc() invalid nxt size

I use this code, with this structure, im trying to make function to add item into array of this structure
typedef struct goods{
char *name;
int num;
} goods;
void addWord(char *what, goods *where, int pnr, int *arrsize, int n){
if (pnr >= *arrsize){
where = (goods*)realloc(where,*arrsize*2*sizeof(goods*));
*arrsize*=2;
}
where[pnr].name = (char*)malloc(strlen(what)*sizeof(char));
strcpy(where[pnr].name,what);
where[pnr].num = n;
}
in main function i have this:
int extstore = 1;
goods *store = (goods*)malloc(1*sizeof(goods*));
addWord(line, store, nr, &extstore, n);
Why am I getting an "invalid next size" runtime-error on the line where = (goods*)realloc(where,*arrsize*2*sizeof(goods*)); in addWord()?
EDIT:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct goods{
char *name;
int r;
} goods;
int main()
{
int linelen, i, nr = 0, current_r;
char *line = NULL;
size_t len = 0;
int extstore = 1;
goods *store;
store = malloc(extstore*sizeof(goods*));
while (1){
while ((linelen = getline(&line, &len, stdin)) != -1){
if (line[linelen - 1] == '\n'){
line[linelen - 1] = '\0';
}
linelen = strlen(line);
if (line[0] == '#'){
if (sscanf(line,"#%d",&current_r) != 1){
printf("bad input.");
return 0;
} else continue;
}
if (nr >= extstore){
store = realloc(store,extstore * sizeof(goods*) * 2);
extstore*=2;
}
store[nr].name = malloc(strlen(line)*sizeof(char));
strcpy(store[nr].name,line);
store[nr].r = current_r;
nr++;
}
if (linelen == -1) break;
}
printf("\n");
for (i = 0;i < nr;i++){
printf("%s, [id:%d]\n", store[i].name, store[i].r);
}
return 0;
}
extstore * sizeof(goods*) * 2
should be extstore * sizeof(goods) * 2 because the space for structures should be allocated - not just for pointers.
There is a fundamental problem in your code. You are passing pointer by value, which means that any change made to a pointer (not the variable pointed to, but the pointer itself) will not be visible from outside the function. You should pass a pointer by pointer instead, and you should check the result returned from realloc. Secondly, don't assign result of realloc back to same pointer - in case of failure you will lost pointer to memory -> thus, memory leak will occur.
To pass pointer by pointer:
void addWord( char *what, goods **where, size, ...) {
if ( *where == NULL) return; // nothing to do
if ( size < 1) return; // it would result in realloc=free call
goods *res = NULL;
res = realloc( *where, size * sizeof( goods));
if ( res != NULL) {
*where = res;
}
else {
// Error (re)allocating memory
// If realloc() fails the original block is left untouched,
// it is not freed or moved, so here *where is unchanged
}
And there is no need in C to cast a result from malloc.
* Error in `path': realloc(): invalid next size: 0x0000000000ec8010 *
This failure must be because "where" is invalid due to a heap corruption earlier in the execution.
C is pass-by-value.
Which means changing an argument in the function does not change the expression it was initialized from.
Thus, the first time realloc moves the memory, the pointer in main will be bad.
To correct that, either use an extra level of indirection, or preferably return the new value as the result.
(Anyway, you should check for allocation failure (malloc and realloc),
and you should not cast from void* to any pointer-type in C.)

Resources