0

I have created a simple C library is generated by one .c and one .h file.

// test.c
#include "test.h"
#include "stdlib.h"
void GetArray(int * array)
{
  array = (int *) calloc(2, sizeof(int));
  array[0] = 0;
  array[1] = 1;
}
// test.h
void GetArray(int * array);

I then generated a C++ executable that would link to the C library and call this function.

// Test.cpp
#include "Test.hpp"

int main(int argc, char *argv[])
{
  int * array;
  GetArray(array);
  delete[] array;
  return 0;
}

with header

// Test.hpp
extern "C" {
#include "test.h"
}

For completeness I include the Makefile

CC  = gcc
CPP = g++

# ----- C-based library -------
testlib.a: test.o
        ar rcs testlib.a test.o

test.o: test.c
        $(CC) -c $<

# ------ C++ executable that links to C-based library -----
Test: Test.o testlib.a
        $(CPP) Test.o -o $@ testlib.a

Test.o: Test.cpp
        $(CPP) -c $<

.PHONY: clean
clean:
        rm -f *.o Test testlib.a

I was surprised to see that despite the delete[] array; call in Test.cpp, that a valgrind LEAK SUMMARY report showed that 8 bytes of memory are definitely lost.

I alternatively tried to create array directly in Test.cpp without the call to the C-library function GetArray. That is

// Test.cpp
#include "Test.hpp"

int main(int argc, char *argv[])
{
  int * array;
  array = new int[2];
  array[0] = 0;
  array[1] = 1;
  delete[] array;
  return 0;
}

and observed that the valgrind report then showed no memory leaks. I am not sure why I can't clean memory from the C++ executable that was allocated in a function defined in the C-library.

4
  • 7
    I don't think its wise to use delete here - use free and you are also not passing a reference to the pointer variable Commented Dec 1, 2023 at 19:11
  • 8
    void GetArray(int * array) allocates memory to a copy of the pointer, which is then discarded. The caller can't free() the memory, so it's a leak. I suggest int *GetArray(void) and the caller does int * array = GetArray(); (talking C not C++). Commented Dec 1, 2023 at 19:12
  • @DanielA.White, I also tried using free, the memory leak is still present. Commented Dec 1, 2023 at 19:13
  • @DanielA.White, after making the changes I do see that it is more appropriate to use free here. Thanks! Commented Dec 1, 2023 at 19:18

2 Answers 2

1

Change this:

void GetArray(int * array)
{
  array = (int *) calloc(2, sizeof(int));
  array[0] = 0;
  array[1] = 1;
}

To this:

void GetArray(int** array)
{
  *array = (int *) calloc(2, sizeof(int));
  (*array)[0] = 0;
  (*array)[1] = 1;
}

Then invoke as follows:

int* array;
GetArray(&array);

Otherwise, if you only declare it as GetArray(int*), then the parameter value array will get overwritten, but the caller's value for array is never changed. Remember, even pointers themselves are passed by value.

A more natural way of course is this:

int* GetArray()
{
  int* array = (int *) calloc(2, sizeof(int));
  array[0] = 0;
  array[1] = 1;
  return array;
}

Then invoked as:

int* array = GetArray();
Sign up to request clarification or add additional context in comments.

Comments

0

To change within the function GetArray the pointer array declared in main you need to pass it to the function by reference.

In C passing by reference means passing an object indirectly through a pointer to it. Thus dereferencing the passed pointer to an object you will get a direct accesss to the object pointed to by the pointer. Otherwise the function will create its own local variable (parameter) initialized by the value of the passed argument and will change the local variable. The variable used as the argument will stay unchanged.

You can imagine your function and its call the following way

GetArray(array);

//...

void GetArray( /*int * patm_array*/)
{
  int *parm_array = array;

  parm_array = (int *) calloc(2, sizeof(int));
  parm_array[0] = 0;
  parm_array[1] = 1;
}

As it is seen it is the local variable parm_array (I renamed the function parameter to distinguish it from the passed variable declared in main) that was changed within the function.

So you need to declare and define the function in C like

void GetArray( int **array )
{
  *array = (int *) calloc(2, sizeof(int));
  ( *array )[0] = 0;
  ( *array )[1] = 1;
}

and call it like

GetArray( &array );

In C++ you could declare and define the function like

void GetArray(int * &array)
{
  array = (int *) calloc(2, sizeof(int));
  array[0] = 0;
  array[1] = 1;
}

and call it like

GetArray( array );

2 Comments

Passing by reference is an option if I were using C++ for this function but I want to use C for that function.
@Tucker I have explained how to pass by reference in C and what is the difference between C and C++ in such a case..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.