4

I have some code to create a new struct and allocate some space for an array of structs. Initially, I allocate space for 1 struct on the array:

static int datasetCount = 0;

int datasetgroup_new(DatasetGroup *dg char *id){

  dg->id = id;

  // Allocate space for a single dataset to start with
  dg->datasets = (Dataset *) malloc(sizeof(Dataset));

  return 0;

}

I then have a function to add another struct ('dataset') to the struct containing the array. At the end of the function, I reallocate the array to provide another space:

void datasetgroup_add(DatasetGroup *dg, string filePath){

  // Create the dataset
  Dataset ds;
  dataset_new(&ds, filePath);

  // Copy the dataset to the dataset array
  dg->datasets[datasetCount] = ds;

  // Increment the dataset counter
  datasetCount++;

  //Grow the array
  dg->datasets = (Dataset *)realloc(dg->datasets, sizeof(Dataset) * (datasetCount + 1));

}

I keeping reading things that hint that in modern C you don't need to do stuff like this. I may be wrong...so is the a more modern/correct way to do this?

Edit:

Sorry, to be clear that I am not using C++ types, I have created a typedef for string:

typedef char* string;
jramm
  • 6,415
  • 4
  • 34
  • 73
  • 2
    Where do you read that? In C++, you have `new` and `delete`, but there are no such things in C. – Colonel Thirty Two Apr 23 '15 at 12:55
  • generally the approach is correct for C. You could use a library that would hide all the hassle under the hood. – user3159253 Apr 23 '15 at 12:55
  • and, if you actually use C++, I would recommend to take a look at the standard [containers library](http://en.cppreference.com/w/cpp/container) and use a container that better fits your specific needs – user3159253 Apr 23 '15 at 12:59
  • No, string is: `typedef char* string`. Sorry, I will edit to be clearer – jramm Apr 23 '15 at 12:59
  • Then if you need a pure-C solution I would use a helper library like [GLib](https://developer.gnome.org/glib/stable/glib-Arrays.html) – user3159253 Apr 23 '15 at 13:01
  • 1
    But this is only a helper, a wrapper, internally it performs the same boring operations like those in your code. – user3159253 Apr 23 '15 at 13:04

2 Answers2

4

As mentioned here there is nothing for this in modern C (C11) standard but you can use libraries like Glib in order to easier memory management or you can use it's data structures like array.

If you use visual studio may be you could find some non-standard function for this in that.

To be more specified in linux, these functions just wrapper for brk() system call and all of them do memory management in user space and their speed and efficiently depend on their algorithms, for example GNU C Library get some space in heap and then manage it for you so not all of your realloc() call end into brk() system call, so do not worry yourself about their efficiently so much. you can use valgrind in order to see your memory profiling.

Parham Alvani
  • 2,305
  • 2
  • 14
  • 25
3

I am not clear what you mean by modern C, however there are two things in the code that I want to mention.

The usage style of realloc is wrong. In case it fails and returns NULL, then the original memory would be leaked. See, for example, Dynamic arrays: using realloc() without memory leaks

The logic of growing memory invokes realloc and thus memory allocation on every addition (i.e. call to datasetgroup_add). It increases the size/capacity of the dynamic array by one. This may not be ideal. The commonly used idiom for growing such memory is to double it whenever the capacity becomes full. That way, cost of memory allocation is amortized (What is amortized analysis of algorithms?) over all the calls.

Community
  • 1
  • 1
Arun
  • 19,750
  • 10
  • 51
  • 60
  • Do you mean [amortized](http://en.wikipedia.org/wiki/Amortized_analysis) rather than memoized? – psmears Apr 23 '15 at 13:36
  • Yes, no doubt. Thank you! – Arun Apr 23 '15 at 13:40
  • @Arun thanks. Your comments on the use of realloc are helpful. For growing memory, I was aware this is relatively costly, however in the context of this program, the processing time required after this array has been fully populated is much much greater than the cost of populating the array. – jramm Apr 23 '15 at 13:57