Realloc Using Way too much Memory - c

I have made a minimal-working example of how to add elements to an array with realloc. This will be expanded in a future program that has many more elements.
#include <stdio.h>//printf
#include <stdlib.h>//malloc, realloc
int main() {
//BEGIN REALLOCATE-ABLE ARRAY
unsigned int *array, loop_variable;
const unsigned int ORIGINAL_ARRAY_SIZE = 4, REALLOC_INDICES = 99;
array = malloc(ORIGINAL_ARRAY_SIZE*sizeof(unsigned int));
for (loop_variable = 0; loop_variable < ORIGINAL_ARRAY_SIZE; loop_variable++) {
array[loop_variable] = loop_variable;
}
//BEGIN REALLOCATION
for (loop_variable = 1; loop_variable < REALLOC_INDICES; loop_variable++) {
array = realloc(array,sizeof(unsigned int)*(ORIGINAL_ARRAY_SIZE+loop_variable));
array[ORIGINAL_ARRAY_SIZE+loop_variable-1] = 2*(ORIGINAL_ARRAY_SIZE+loop_variable-1);
printf("reallocate array[%d] = %d\n",ORIGINAL_ARRAY_SIZE+loop_variable-1,array[ORIGINAL_ARRAY_SIZE+loop_variable-1]);
}
//BEGIN PRINTING ARRAY VALUES
for (loop_variable = 0; loop_variable < ORIGINAL_ARRAY_SIZE+REALLOC_INDICES-1; loop_variable++) {
printf("array[%d] = %d\n",loop_variable,array[loop_variable]);
}
//BEGIN FREE ARRAY
free(array); array = NULL;
return 0;
}
This should compile on any computer with gcc or clang. I then run this program on valgrind to ensure there are no memory leaks, and I get this:
==10791== HEAP SUMMARY:
==10791== in use at exit: 0 bytes in 0 blocks
==10791== total heap usage: 99 allocs, 99 frees, 20,988 bytes allocated
==10791==
==10791== All heap blocks were freed -- no leaks are possible
==10791==
==10791== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==10791== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
However, what troubles me is that I'm using 20,988 bytes for a 101-element array. The memory use grows exponentially as the array gets bigger, instead of linearly by 4 bytes/element.
If I'm understanding Valgrind's output correctly, this array should have 4*101 elements = 404 bytes memory size, but appears to use about 50 times as much memory as it should. This is a trivial problem for such a small program, but more meaningful programs will run out of memory on this computer.
My question: is this array really using 20,988 bytes, or is Valgrind double-counting the memory?
Is there a more memory-efficient way to do this? I can't understand other examples of realloc, though I have tried to follow them as closely as I can and make this question relevant to as many users as possible.

==10791== in use at exit: 0 bytes in 0 blocks
==10791== total heap usage: 99 allocs, 99 frees, 20,988 bytes allocated
is this array really using 20,988 bytes
No, it's using 0 bytes.
“allocated” obviously means “ever allocated”, including bytes that have been freed, since the amount of memory “still allocated” is zero (and another line tells you that).

The answer, thanks to user Pascal Cuoq, is that Valgrind will sum the memory allocations for every allocation. This is why I was confused, and thought that realloc was using too much memory.
I thought that if you want to find the size of the array, you can comment out the line that says
free(array); array = NULL;
to intentionally introduce a memory bug, and Valgrind will output
==11699== LEAK SUMMARY:
==11699== definitely lost: 408 bytes in 1 blocks
==11699== indirectly lost: 0 bytes in 0 blocks
==11699== possibly lost: 0 bytes in 0 blocks
==11699== still reachable: 0 bytes in 0 blocks
==11699== suppressed: 0 bytes in 0 blocks
==11699==
==11699== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==11699== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
which gives you the true size of the array at its last iteration. There is probably a better way to do this, but my point is made.
I added improvements suggested by other users here. I had a very difficult time finding good, minimal working examples of realloc on search engines, and for future use of anyone finding this on a search engine, this is very basic minimal working example of a good, but probably not best, how to use realloc in C:
#include <stdio.h>//include printf function
#include <stdlib.h>//include malloc, realloc functions
int main() {
/*BEGIN REALLOCATE-ABLE ARRAY*/
unsigned int *array, loop_variable;
const unsigned int ORIGINAL_ARRAY_SIZE = 4, REALLOC_INDICES = 99999;
array = malloc(ORIGINAL_ARRAY_SIZE*sizeof(unsigned int));
for (loop_variable = 0; loop_variable < ORIGINAL_ARRAY_SIZE; loop_variable++) {
array[loop_variable] = loop_variable;
}
/*BEGIN REALLOCATION*/
for (loop_variable = 1; loop_variable < REALLOC_INDICES; loop_variable++) {
array = realloc(array,sizeof(unsigned int)*(ORIGINAL_ARRAY_SIZE+loop_variable));
if (array == NULL) {
printf("Array variable %d failed to reallocate :,-(\n",loop_variable);
exit(EXIT_FAILURE);
}
array[ORIGINAL_ARRAY_SIZE+loop_variable-1] = 2*(ORIGINAL_ARRAY_SIZE+loop_variable-1);
printf("reallocate array[%d] = %d\n",ORIGINAL_ARRAY_SIZE+loop_variable-1,array[ORIGINAL_ARRAY_SIZE+loop_variable-1]);
}
/*BEGIN PRINTING ARRAY VALUES*/
for (loop_variable = 0; loop_variable < ORIGINAL_ARRAY_SIZE+REALLOC_INDICES-1; loop_variable++) {
printf("array[%d] = %d\n",loop_variable,array[loop_variable]);
}
/*BEGIN FREE ARRAY*/
free(array); array = NULL;
return 0;
}

Related

How do I fix these memory leaks in C?

I am working on a function which allocates memory into an array, and then I free it later. Oddly enough, valgrind is giving me this error:
==93== HEAP SUMMARY:
==93== in use at exit: 11,160 bytes in 2,232 blocks
==93== total heap usage: 44,310 allocs, 42,078 frees, 1,632,230 bytes allocated
==93==
==93== 11,160 bytes in 2,232 blocks are definitely lost in loss record 1 of 1
==93== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==93== by 0x10976F: FillHashMap (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/flwp)
==93== by 0x1092F1: main (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/flwp)
==93==
==93== LEAK SUMMARY:
==93== definitely lost: 11,160 bytes in 2,232 blocks
==93== indirectly lost: 0 bytes in 0 blocks
==93== possibly lost: 0 bytes in 0 blocks
==93== still reachable: 0 bytes in 0 blocks
==93== suppressed: 0 bytes in 0 blocks
==93==
==93== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Dr. Memory is giving me a similar error:
Error #1: UNADDRESSABLE ACCESS: reading 0x0000000000000000-0x0000000000000008 8 byte(s)
# 0 testing [C:/Users/Jordan/Documents/GitHub/flwg/FLWP-2.c:120]
# 1 main [C:/Users/Jordan/Documents/GitHub/flwg/FLWP-2.c:105]
Note: #0:00:01.195 in thread 14704
Note: instruction: mov (%rax) -> %rax
The strcmp line of code is what causes it to break with Dr. Memory, although valgrind says I have issues even if I don't call this particular method.
void testing(struct wordConnections *header){
header = header->nextRow;
while(strcmp(header->word, "berk") != 0){
header = header->nextRow;
if(header == NULL){
printf("Failed");
return;
}
}
}
The code that runs is (the value and significance of numLetters + 1 is it is the length of the char* stored in the wordStorage, the value of numLetters is 4):
char** FillHashMap(struct wordConnections **(*HashMap)){
int h = 0;
/* The Amount of words in each file, File 1, 2, 3 */
int totalWordQuantity[3] = {132, 7420, 19829};
/*the word that we test, we add by two because first 4: word, 5th: \n, 6th: \0*/
char word[numLetters + 1];
/*how many times we've changed the character*/
int letterSpot = 0;
/*the character that goes through the file*/
char c;
FILE *flwd = OpenFile();
/* is it the first word of the line */
int wordCount = 0;
int isFirst = 1;
char p = fgetc(flwd);
c = p;
/* So, this is a temporary word, who will store the row, so all of its category folks will be contained within it */
char* rowWord = malloc(sizeof(char) * (numLetters + 1));
/*This stores all of the words*/
char** wordStorage = (char**)calloc(totalWordQuantity[numLetters - 2], sizeof(char*) * (numLetters + 1));
int i = 0;
/* First, take the character */
while((c = p) != EOF){
p = fgetc(flwd);
/* Add the character to the word */
word[letterSpot] = c;
/* Allows the letter spot to find the next place into the word */
letterSpot++;
/* Determines if the character is the placement immediately after the word */
if((c == ' ' && p != '\n') || c == '\n'){
letterSpot = 0;
/* Throws in the \0, converting into a string */
word[numLetters] = '\0';
wordStorage[wordCount] = malloc(sizeof(char) * (numLetters + 1));
h++;
strcpy(wordStorage[wordCount], word);
/* Determine if it's the first word */
if(isFirst == 1){
strcpy(rowWord, word);
/* Throw it in as a row */
AddRow2DLL(wordStorage[wordCount],
HashMap[FirstHashFunction(word[0])/*First Letter*/]
[SecondHashFunction(word)]/*First Vowel*/);
}
/* If it's not the first word */
else {
AddColumn2DLL(wordStorage[wordCount],
HashMap[FirstHashFunction(rowWord[0])/*First Letter*/]
[SecondHashFunction(rowWord)]/*First Vowel*/);
}
if(c == ' '){
isFirst = 0;
}
if(c == '\n'){
isFirst = 1;
}
wordCount++;
}
c = p;
}
free(rowWord);
fclose(flwd);
return wordStorage;
}
The hash map works fine, this is the method that causes the issues, without it, there are no memory leaks.
Later in the code, I free the wordStorage array with this method:
void FreeWordStorage(char** wordStorage){
int f = 0;
/* The Amount of words in each file, File 1, 2, 3 */
int totalWordQuantity[3] = {132, 7420, 19829};
int i;
for(i = 0; i < totalWordQuantity[numLetters - 2]; i++){
free(wordStorage[i]);
f++;
}
free(wordStorage);
}
I've tried all sorts of things to fix it. Oddly enough, when I check it with integers, I'm allocating and freeing the same amount of data.
Any help would be greatly appreciated. Thank you!
Valgrind's analysis indicates that the leaked memory was allocated by a bunch of malloc() calls by function FillHashMap(), and the only plausible candidate for those is this:
wordStorage[wordCount] = malloc(sizeof(char) * (numLetters + 1));
Function FreeWordStorage() appears to be correct for freeing the data allocated by FillHashMap(), so if some allocations are going unfreed then there are two main possibilities:
The pointer value returned by FillHashMap() is not later passed to FreeWordStorage(). The latter function might not be called at all on the code path that is being exercised, or perhaps a modified or outright wrong pointer is being passed to it.
Or,
Some or all of the pointers recorded in the allocated block returned by FillHashMap() are modified after being recorded, so that when it is called, FreeWordStorage() is ineffective at freeing the allocated memory.
Either one of those could be consistent with Dr. Memory's diagnostic, but whichever scenario applies, it does not appear to play out in the code presented in the question. I am reasonably confident that your pointers are being mangled somewhere else in the program.

Two different memory errors depending on where I allocate the memory

For my C program I have tried to allocate memory for a double array(ssi) which I then access in another function (spslicer). If I allocate this memory before I call a different function (kpmdos) which should be unrelated I get the error:
*** glibc detected *** ./SpecSli.ex: double free or corruption (!prev): 0x0000000000a86e40 ***
and if I allocate it after I get the error:
malloc.c:3830: _int_malloc: Assertion `(unsigned long)(size) >= (unsigned long)(nb)' failed.
Based on this I think that I did something wrong in kpmdos when I allocated the memory but I cannot see anything wrong:
void kpmdos(csptr A, int Mdeg, double nvec, double ctr, double wid, int n, double *mu){
// initialize variables
double *w = malloc(n*sizeof(double));
//free(w);
fill_rand(n, w);
double *v = malloc(n*sizeof(double));
divide_array(w, norm(w, n), v, n);
double *vkm1 = malloc(n*sizeof(double));
fill(n, 0, vkm1);
double *vk = malloc(n*sizeof(double));
memcpy(vk,v, n*sizeof(double));
double *temp = malloc(n*sizeof(double));
double *vkp1 = malloc(n*sizeof(double));
double thet = pi/(Mdeg+1);
double a1 = 1/(Mdeg+2.0);
double a2 = sin(thet);
double jac;
double scal;
Then I do some other coding with no memory allocation.
free(w);
free(vkp1);
free(vkm1);
free(temp);
free(vk);
free(v);
}
The output using valgrind when it is allocated before the function is:
> > ==7045== HEAP SUMMARY:
> ==7045== in use at exit: 46,452 bytes in 235 blocks
> ==7045== total heap usage: 351 allocs, 116 frees, 66,700 bytes allocated
> ==7045==
> ==7045== LEAK SUMMARY:
> ==7045== definitely lost: 22,331 bytes in 146 blocks
> ==7045== indirectly lost: 0 bytes in 0 blocks
> ==7045== possibly lost: 0 bytes in 0 blocks
> ==7045== still reachable: 24,121 bytes in 89 blocks
> ==7045== suppressed: 0 bytes in 0 blocks
> ==7045== Rerun with --leak-check=full to see details of leaked memory
> ==7045==
> ==7045== For counts of detected and suppressed errors, rerun with: -v
> ==7045== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
Please let me know if you know the problem or if you need more information.
Thank you all for your help. I finally figured out most of it. During my coding which I did not post I had a function which would change all the variables in an array to something different and for this function I was inputting the wrong array size.

C freeing multi-dimensional array inside a struct seems incorrect

I've seen another question for allocating and freeing multi-dimensional arrays, but I suspect that it does not free correctly. For testing I made this small code extracted from my main code.
I compiled it under MacOS X.10 with XCode or gcc 4.9 with same results:
Faulty code
It runs 200000 times and the memory consumption grows up to 20GB!:
#include <stdlib.h>
typedef struct{
int lonSize;
int latSize;
double **grid;
}raf09_grid_t;
static raf09_grid_t raf09_grid;
void free_raf09_grid() {
if (raf09_grid.grid != NULL) {
int i;
for (i = 0; i < raf09_grid.lonSize; ++i) {
free(raf09_grid.grid[i]);
}
free(raf09_grid.grid);
}
raf09_grid.latSize = 0;
raf09_grid.lonSize = 0;
}
void get_raf09_grid() {
int nbElLat=381;
int nbElLon=421;
raf09_grid.grid = malloc(nbElLon*sizeof(double*));
int it;
for(it=0;it<nbElLon;it++)
raf09_grid.grid[it] = malloc(nbElLat*sizeof(double));
int i,j;
for(i=0;i<420;i++) {
for(j=0;j<380;j++) {
raf09_grid.grid[i][j]=0.0;
}
}
}
int main (int argc, char *argv[]) {
int i=0;
for (i=0;i<20000;i++) {
get_raf09_grid();
free_raf09_grid();
}
return 0;
}
I'm newbie so I suspect that my freeing is not correct...
Corrected code
With your help I corrected my code, it is now corrects and takes only 10M in ram:
#include <stdlib.h>
typedef struct{
int lonSize;
int latSize;
double **grid;
}raf09_grid_t;
static raf09_grid_t raf09_grid;
void free_raf09_grid() {
if (raf09_grid.grid != NULL) {
int i;
for (i = 0; i < raf09_grid.lonSize; ++i) {
free(raf09_grid.grid[i]);
}
free(raf09_grid.grid);
}
raf09_grid.latSize = 0;
raf09_grid.lonSize = 0;
}
void get_raf09_grid() {
raf09_grid.latSize=381;
raf09_grid.lonSize=421;
raf09_grid.grid = malloc(raf09_grid.lonSize*sizeof(double*));
int it;
for(it=0;it<raf09_grid.lonSize;it++)
raf09_grid.grid[it] = malloc(raf09_grid.latSize*sizeof(double));
int i,j;
for(i=0;i<420;i++) {
for(j=0;j<380;j++) {
raf09_grid.grid[i][j]=0.0;
}
}
}
int main (int argc, char *argv[]) {
int i=0;
for (i=0;i<20000;i++) {
get_raf09_grid();
free_raf09_grid();
}
return 0;
}
Valgrind is an invaluable tool in tracing memory leaks. Compiling your source code with debug information, and running it with:
valgrind --leak-check=full -v ./a.out
will give the following summary:
==7033== HEAP SUMMARY:
==7033== in use at exit: 1,283,208,000 bytes in 421,000 blocks
==7033== total heap usage: 422,000 allocs, 1,000 frees, 1,286,576,000 bytes allocated
==7033==
==7033== Searching for pointers to 421,000 not-freed blocks
==7033== Checked 92,040 bytes
==7033==
==7033== 18,288 bytes in 6 blocks are possibly lost in loss record 1 of 2
==7033== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7033== by 0x400611: get_raf09_grid (grid.c:27)
==7033== by 0x4006A8: main (grid.c:39)
==7033==
==7033== 1,283,189,712 bytes in 420,994 blocks are definitely lost in loss record 2 of 2
==7033== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7033== by 0x400611: get_raf09_grid (grid.c:27)
==7033== by 0x4006A8: main (grid.c:39)
==7033==
==7033== LEAK SUMMARY:
==7033== definitely lost: 1,283,189,712 bytes in 420,994 blocks
==7033== indirectly lost: 0 bytes in 0 blocks
==7033== possibly lost: 18,288 bytes in 6 blocks
==7033== still reachable: 0 bytes in 0 blocks
==7033== suppressed: 0 bytes in 0 blocks
==7033==
==7033== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)
--7033--
--7033-- used_suppression: 2 dl-hack3-cond-1
==7033==
==7033== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)
The link to line 27 shows that there is a problem with this statement:
raf09_grid.grid[it] = malloc(nbElLat*sizeof(double));
You are allocating more memory here than is being freed later in the program.
Update the raf09_grid.lonSize variable in get_raf09_grid() to equal nbElLon, and it fixes the problem.
In general, every malloc should have a corresponding free. Once you know which malloc is leaking, then you can find the code that is supposed to free that variable, and debug from there.
Note: I reduced the loop from 20000 to 1000, but it will give you the same information.
After reading through yoiur question, here are a few suggestions:
In the code:
for(i=0;i<420;i++) {
for(j=0;j<380;j++) {
raf09_grid.grid[i][j]=0.0;
}
you are looping i and j for 420 and 380, while you've defined :
int nbElLat=381;
int nbElLon=421;
So, you never process the 420th iteration for the Longitudes. The same with missing out on the 380th loop for Latitude.
If that's a desirable thing, its fine, else you should fix it to something like this:
for(i=0;i<nbElLon;i++) { //better use macros or variable names than just plain magic numbers
for(j=0;j<nbElLat;j++) {
raf09_grid.grid[i][j]=0.0;
}
Second, in your free_raf09_grid() function, you use:
for (i = 0; i < raf09_grid.lonSize; ++i) {
but you haven't initialized that variable anywhere.
Perhaps in function get_raf09_grid() just before the declaration of int i,j do this:
raf09_grid.lonSize = nbElLon;
raf09_grid.latSize = nbElLat;
The third important one.
In the lines below:
raf09_grid.grid = malloc(nbElLon*sizeof(double*));
int it;
for(it=0;it<nbElLon;it++)
raf09_grid.grid[it] = malloc(nbElLat*sizeof(double));
you should check if the mallocs have returned success or not aka check for NULL.
your for loop uses lonSize as a parameter, but it doesn't get updated anywhere

[C]Malloc problems

I'm trying to write a program that uses some basic threading for an assignment. Below are the relevant snippets that I think are causing the problem.
The program runs fine with 25 or less threads but usually results in a segfault when 26 or more are used. This led me to think that my malloc statement were incorrect. Can anyone nudge me in the right direction? If you need more code to be posted, I'd be happy to provide it.
Also, these problems only come up when I run the program on my school's student machines. It appears to work fine my local machine. Might anyone know why?
Thanks for your time!
...
struct thread_args {
struct bitmap *bm;
double xmin;
double xmax;
double ymin;
double ymax;
int max;
int start;
int end;
};
...
int num_threads; //Given by user input
struct bitmap *bm = bitmap_create(500, 500); //All threads share the same bitmap
int i;
pthread_t *thread_id = malloc(num_threads * sizeof(*thread_id));
struct thread_args *args = malloc(num_threads * sizeof(*args));
for (i = 0; i < num_threads; i++) {
args[i].bm = bm;
args[i].xmin = xcenter-scale;
args[i].xmax = xcenter+scale;
args[i].ymin = ycenter-scale;
args[i].ymax = ycenter+scale;
args[i].max = max;
args[i].start = bitmap_height(bm) * i / num_threads;
args[i].end = bitmap_height(bm) * (i + 1) / num_threads;
pthread_create(&thread_id[i], NULL, compute_image, &args[i]);
}
for (i = 0; i < num_threads; i++) {
pthread_join(thread_id[i], NULL);
}
...
void* compute_image(void *arg)
{
struct thread_args* args = (struct thread_args*) arg;
int i,j;
int width = bitmap_width(args->bm);
int height = bitmap_height(args->bm);
// For every pixel in the image...
for(j=args->start;j<args->end;j++) {
for(i=0;i<width;i++) {
// Determine the point in x,y space for that pixel.
double x = args->xmin + i*(args->xmax-args->xmin)/width;
double y = args->ymin + j*(args->ymax-args->ymin)/height;
// Compute the iterations at that point.
int iters = iterations_at_point(x,y,args->max);
// Set the pixel in the bitmap.
bitmap_set(args->bm,i,j,iters);
}
}
return 0;
}
...
valgrind log
==24919==
==24919== HEAP SUMMARY:
==24919== in use at exit: 1,000,000 bytes in 1 blocks
==24919== total heap usage: 56 allocs, 55 frees, 1,018,884 bytes allocated
==24919==
==24919== Searching for pointers to 1 not-freed blocks
==24919== Checked 87,112 bytes
==24919==
==24919== 1,000,000 bytes in 1 blocks are definitely lost in loss record 1 of 1
==24919== at 0x4A069EE: malloc (vg_replace_malloc.c:270)
==24919== by 0x401256: bitmap_create (bitmap.c:21)
==24919== by 0x400CEC: main (mandel.c:103)
==24919==
==24919== LEAK SUMMARY:
==24919== definitely lost: 1,000,000 bytes in 1 blocks
==24919== indirectly lost: 0 bytes in 0 blocks
==24919== possibly lost: 0 bytes in 0 blocks
==24919== still reachable: 0 bytes in 0 blocks
==24919== suppressed: 0 bytes in 0 blocks
==24919==
==24919== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)
--24919--
--24919-- used_suppression: 4 U1004-ARM-_dl_relocate_object
--24919-- used_suppression: 2 glibc-2.5.x-on-SUSE-10.2-(PPC)-2a
==24919==
==24919== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)
Edit: Added compute_image code and valgrind log although the log is missing the error messages it was showing earlier today. The 1,000,000 bytes lost is something I know about.
Make sure that pthread_create is not returning an error. The machine has a global limit on the number of threads that can be spawned, and is probably fluctuating close to that limit. If you fail to spawn a thread, you will have a garbage pthread_t, which will likely cause pthread_join to blow up.

Why does my implementation of a dynamic string array leak?

I need a string array which dynamically resizes when more items are added to it. I got the basic code working, but valgrind reports memory leaks.
The implementation which should work with static and dynamically allocated strings looks like this:
typedef struct {
char **items;
int num;
} StringArray;
StringArray* string_array_init() {
StringArray *arr = malloc(sizeof(StringArray));
arr->items = NULL;
arr->num = 0;
return arr;
}
void string_array_add(StringArray *arr, char *str, int str_len) {
void *new_items = realloc(arr->items, (arr->num + 1) * sizeof(char *));
arr->items = (char**)new_items;
arr->items[arr->num] = strndup(str, str_len);
arr->num++;
}
void string_array_cleanup(StringArray *arr) {
int i;
for (i = 0; i < arr->num ; i++) {
free(arr->items[i]);
}
free(arr);
}
int main() {
StringArray *arr = string_array_init();
string_array_add(arr, "item 1", strlen("item 1"));
string_array_add(arr, "item 2", strlen("item 2"));
string_array_add(arr, "item 3", strlen("item 3"));
string_array_cleanup(arr);
return 0;
}
Valgrind reports:
==31443== HEAP SUMMARY:
==31443== in use at exit: 12 bytes in 1 blocks
==31443== total heap usage: 7 allocs, 6 frees, 53 bytes allocated
==31443==
==31443== 12 bytes in 1 blocks are definitely lost in loss record 1 of 1
==31443== at 0x4025CCD: realloc (vg_replace_malloc.c:525)
==31443== by 0x80484A6: string_array_add (in ...)
==31443== by 0x8048593: main (in ...)
==31443==
==31443== LEAK SUMMARY:
==31443== definitely lost: 12 bytes in 1 blocks
==31443== indirectly lost: 0 bytes in 0 blocks
==31443== possibly lost: 0 bytes in 0 blocks
==31443== still reachable: 0 bytes in 0 blocks
==31443== suppressed: 0 bytes in 0 blocks
==31443==
Why is realloc leaking and how can I fix it? I thoght freeing every string separately and then freeing the struct would be enough, but I´m missing something.
You free the strings contained in arr->items, but you don't free arr->items itself. (You allocated it in string_array_add).
The problem is with this line:
arr->items = (char**)new_items;
You overwrite the old pointer. You need to realloc this pointer and not new_items.

Resources