Idiomatic macros for malloc in C?

Viewed 110

Background

I am learning low-level dev after working with C++ for high level projects for a decent stretch. Currently bumbling about typical C patterns and stumbling across bits of the linux kernel and old emails.

Question

Are there a set of commonly used/idiomatic macros, or generic functions which reduce repetition or reduce mistakes in memory allocation?

Something I see a lot in my code is long multiplication statements inside of malloc which I see as tedious, and a ripe place for problems. Example:

struct my_struct {
    size_t size;
    char* memory;
}

struct my_struct* my_struct_new(size_t size) {
    struct my_struct* ms = malloc(sizeof *ms)
    
    ms->size = size;
    ms->memory = malloc(size * sizeof *ms->memory);

    return ms;
}

I'm trying to avoid creating an XY problem through giving my bad tries here.

Thank you for your time.

2 Answers

Nope, that's pretty much the idiomatic way to allocate memory in C. The *alloc functions don't know or care about types, they only care about how many bytes you want. The best way to get that number (for things other than strings or byte buffers, anyway) is to multiply the size of the target (sizeof *ms->memory) by the number of elements you want (size). Otherwise you can use calloc which passes those things as separate arguments, but calloc will zero-initialize the memory, which may or may not be what you want.

You can and should abstract out complex allocations into their own functions (as this snippet does). but as far as any existing convenience macros - not really.

Are there a set of commonly used/idiomatic macros, or generic functions which reduce repetition or reduce mistakes in memory allocation?

Not really, @John Bode has it mostly covered.

Make a allocator function for struct my_struct - very idiomatic in C.

Minor weakness in the implementation is the lack of checking for out-of-memory - something expected with robust code.

struct my_struct* my_struct_new(size_t size) {
    struct my_struct *ms = malloc(sizeof *ms)
    if (ms) {
      ms->size = size;
      ms->memory = malloc(size * sizeof *ms->memory);
      if (ms->memory == NULL) {
        free(ms);
        ms = NULL;
      }
    }
    return ms;
}

Also research Flexible array member

struct my_struct_fma {
    size_t size;
    char memory[];
}

struct my_struct_fma *my_struct_new_fma(size_t size) {
    struct my_struct_fma *ms = malloc(sizeof *ms + sizeof *ms->memory * size);
    if (ms) {
      ms->size = size;
      }
    }
    return ms;
}
Related