0

Im codeing a little Ringbuffer in C, everything works, but if i check for memoryleeks, there is the following message:

It looks like , the "write_buffer" function causes the leak, but i cant figure out why.

valgrind --leak-check=full --track-origins=yes ./buf==3601== Memcheck, a memory error detector
==3601== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==3601== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==3601== Command: ./buf
==3601== 
start:0first:asecond:bfree element 0 
==3601== Invalid free() / delete / delete[] / realloc()
==3601==    at 0x402AF06: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3601==    by 0x8048711: delete_buffer(buffer*, int) (ringbuffer.cpp:38)
==3601==    by 0x8048895: main (ringbuffer.cpp:84)
==3601==  Address 0x8048985 is not stack'd, malloc'd or (recently) free'd
==3601== 
==3601== 
==3601== HEAP SUMMARY:
==3601==     in use at exit: 15 bytes in 3 blocks
==3601==   total heap usage: 6 allocs, 6 frees, 45 bytes allocated
==3601== 
==3601== 15 bytes in 3 blocks are definitely lost in loss record 1 of 1
==3601==    at 0x402BB7A: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3601==    by 0x8048684: create_buffer(buffer*, int, int) (ringbuffer.cpp:23)
==3601==    by 0x80487F9: main (ringbuffer.cpp:74)
==3601== 
==3601== LEAK SUMMARY:
==3601==    definitely lost: 15 bytes in 3 blocks
==3601==    indirectly lost: 0 bytes in 0 blocks
==3601==      possibly lost: 0 bytes in 0 blocks
==3601==    still reachable: 0 bytes in 0 blocks
==3601==         suppressed: 0 bytes in 0 blocks
==3601== 
==3601== For counts of detected and suppressed errors, rerun with: -v
==3601== ERROR SUMMARY: 4 errors from 2 contexts (suppressed: 0 from 0)

my code:

/*Ringbuffer->c*/
#include <stdlib.h>
#include <stdio.h>
struct buffer {
int size;
int start;
int pos;            // position of current free element
const char ** elements;
};

void create_buffer(buffer *buf, int buf_size, int elem_size){
int i =0;
buf->size =buf_size;
buf->start=0;
buf->pos=0;
    buf->elements = (const char**) malloc(buf_size*sizeof(const char *));
    if(buf->elements == NULL)
        {
        printf("out of memory\n");
        }
    for(i = 0; i < buf_size; i++)
        {
        buf->elements[i] = (const char*) malloc(elem_size * sizeof(const char));
        printf("malloc element %i \n",i);
        if(buf->elements[i] == NULL)
            {
            printf("out of memory\n");
            }
        }

}
void delete_buffer(buffer *buf,int buf_size)
{
int i=0;

   for(i=0;i<buf_size;i++)
   {
    printf("free element %i \n",i);
    free((void*)buf->elements[i]);
   }

free((void*)buf->elements);

}
void write_buffer(buffer *buf,const char* element){
    buf->elements[(buf->start+buf->pos)]=element;
    buf->pos++;
}


const char* read_buffer(buffer *buf){

    const char* ret=buf->elements[buf->start];
    buf->start++;
    return ret;
}


int buffer_is_full(buffer *buf){
    if(buf->size==buf->pos){
            return 1;
        }
    return 0;
}

int buffer_is_empty(buffer *buf){
    if(buf->size==buf->pos){
        return 1;
    }
    return 0;
}

int main (int arc, const char **argv){
    buffer buf;


    create_buffer(&buf,5,5);

    printf("start:%i",buf.pos);

    write_buffer(&buf,"a");
    write_buffer(&buf,"b");
    write_buffer(&buf,"b");
    printf("first:%s",read_buffer(&buf));
    printf("second:%s",read_buffer(&buf));

    delete_buffer(&buf,5);

}
Zodoh
  • 100
  • 7
  • 1
    [Please don't cast the return value of `malloc()` in C](http://stackoverflow.com/a/605858/28169). Also, it can't ever be `const` or you wouldn't need the `malloc()`. The `const` type of `elements` doesn't make sense. – unwind Feb 07 '14 at 13:54
  • Avoid pointers - use std::containers or std::shared/unique_ptr –  Feb 07 '14 at 13:55
  • @fritzone, indeed it is! – hmjd Feb 07 '14 at 13:56
  • 1
    @Dieter Lücking There are no std::containers or std::shared/unique_ptr in C – TNA Feb 07 '14 at 13:59
  • @TNA Thanks (and no thanks) - I ran into this from a C++ tag –  Feb 07 '14 at 14:11
  • Try this: `buf->elements[(buf->start+buf->pos)] = strdup(element);` – alk Feb 07 '14 at 14:24

1 Answers1

1

You are trying to free a const value. write_buffer(&buf,"a"); puts a const in the buffer. You cannot free that!

Ferenc Deak
  • 34,348
  • 17
  • 99
  • 167
  • Although `"a"` is constant (as being a literal), the `const` modifier does not make the program choke. However 1+ for pointing out the root cause to the issue. – alk Feb 07 '14 at 14:22