Home > Software engineering >  C API: Return allocated array of user given size
C API: Return allocated array of user given size

Time:10-13

I'm implementing a C API that exposes some data collected from a systemd service. The header of the API contains two structs:

typedef struct Info {
  int latest;
  int prev;
  int cur;
} Info;

typedef struct InfoArray {
  Info *info;
} InfoArray;

The implementation of this C header is written in C and I plan to offer a create(size_t size) function to let the user create a new struct with an array of the user entered size. This returned array can then later be passed by reference to another function to fill it with data until the array has reached the size defined by the user.

How would I achieve this?

Edit: I'm looking for a way to return the allocated array of size n, however I tried the following:

InfoArray *create(size_t size) {
  InfoArray *array = (InfoArray *)malloc(size * sizeof(Info));
  return array;
}

which should return a allocated array, but when trying to delete the array on the client side by calling delete info I get an error that I cannot free this handle, so how would i let the consumer of the API manage the deletion of the memory?

Since the implementation is written in a .cpp file (C ) i figured there must be a way to return it by using the new operator, but I've failed on implementing it like this.

CodePudding user response:

When using malloc(), to clear the object you have to use free(). This is the C way of doing things.

When using C , use new and delete instead, like this: InfoArray *array = new InfoArray[size];

However, when going with C i would urge you to just dump the InfoArray thing and roll with something like std::vector<Info>.

Edit:

The implementation of this C header is written in C

This doesn't make sense. It's either a C unit or a C unit. Those are two separate languages, you only get to pick one. Similiar syntax and good interfaceability do not change that.

CodePudding user response:

I see "I'm implementing a C API", so the interface is C, I understand.
I see "implementation of this C header is written in C " so the code behind the interface is C by your design.
I see "trying to delete the array on the client side by calling delete info", so the calling code is also C .

Strictly speaking, it would be imaginable to use something with a C interface from C and to even implement it in C with a C interface. I just really hope it is not what OP wants.
But whatever comes out of a C interface will never be accepted by delete, the C code which uses the C interface has to accept that it is a C interface and use free() on the malloced pointer.
That is why I recommend to redesign the interface. Either drop the C interface between two pieces of C in favor of a C interface. Or go with the C interface and drop the idea to use delete.

CodePudding user response:

how would i let the consumer of the API manage the deletion of the memory?

Problems with freeing is one of the reasons why C idiom is for the caller to provide a buffer:

int fillInfo(InfoArray *array, size_t arraySize) {
  memcopy...
  return countCopied;
}

In this approach the API never allocates anything, it only copies the data to provided buffers. Just like strcpy. The huge upside of this approach is that client can use whatever allocation methods they deem appropriate at the moment.

If you really must return a new buffer then provide a pair of methods:

InfoArray *create(size_t size);
void release(array* InfoArray);

This way clients don't know nor care how the objects are allocated and freed. This is useful when you want to restrict the client how the memory is allocated, but note that the client is still responsible for memory management, it's just limited to one option. And it still doesn't guarantee the client won't use memory allocated in unapproved ways.

Keeping allocation and freeing on 2 sides of the demarcation line between client and library is asking for trouble. You're hiding from the client author how the memory was allocated, and yet you require them to use correct deallocation method. Which is precisely the culprit here.

  • Related