Broseph
Broseph

Reputation: 1753

flexible mpz_t array in struct

I have a struct like this:

typedef struct{
    size_t length; // length of the array
    size_t numbits; // number of bits allocated per val in vals
    mpz_t vals[]; // flexible array to hold some number of mpz_t array
} CoolArray;

Ok, so it's a normal flexible array, and I should be able to use malloc to set it's size:

void initArray(CoolArray* array, size_t length, size_t numbits){
    assert(length>=1); // don't make arrays with a length<=0

    // first I allocate memory for vals...
    array->vals = (mpz_t*) malloc(sizeof(CoolArray)+length*sizeof(mpz_t));

    // then I allocate memory for each val in vals
    mpz_array_init(array->vals, (size_t)length, numbits);

    return;
}

but when I try to use this, I get a segmentation fault. I also get complaints about incorrect use of mpz_array_init. But I've looked at the manula, and it seems I am doing this correctly.

I also tried to use my struct like this:

typedef struct{
    size_t length; // length of the array
    size_t numbits; // number of bits allocated per val in vals
    mpz_t* vals; // pointer to start of array
} CoolArray;

and I also changed my initArray function to this:

void initArray(CoolArray* array, size_t length, size_t numbits) {
    assert(length>=1); // don't make arrays with a length<=0

    // first I allocate memory for vals...
    array->vals = (mpz_t*) calloc(length, sizeof(mpz_t));

    // then I allocate memory for each val in vals
    mpz_array_init(array->vals, (size_t)length, numbits);

    return;
}

This one doesn't segfault, but I get complaints at compile time about incorrect usage of mpz_array_init, and I also get a bunch of malloc errors in my output, along with the output I want to see. Can anyone tell me where my code is incorrect? why does the first version segfault? I did it the way people seem to recommend. And why does the compiler complain about mpz_array_init being used incorrectly?

This is the sort of error i get in my output:

gmpascal(80964) malloc: *** error for object 0x100801088: Non-aligned
pointer being freed *** set a breakpoint in malloc_error_break to debug

P.S. gmpascal is the name of my executable, it computes the nth row of pascals triangle.

P.P.S. I'm compiling with gcc-4.2 on a Powermac with these flags:

-arch ppc64 -o gmpascal gmpascal.c -lgmp -Wall

Is there something I missing here?

Upvotes: 5

Views: 1655

Answers (2)

ecatmur
ecatmur

Reputation: 157314

If you're using a flexible array member, you need to allocate the struct in one go:

CoolArray *array = malloc(sizeof(CoolArray) + length * sizeof(mpz_t));
mpz_array_init(array->vals, length, numbits);

Upvotes: 0

WhozCraig
WhozCraig

Reputation: 66194

Keep in mind, I do NOT program gmp, but a tail-dynamic buffer in a struct is usually implemented something like this (adapted to how I think you want to use it):

typedef struct
{
  size_t length;  //length of the array
  size_t numbits; //number of bits allocated per val in vals
  mpz_t vals[1];  //flexible array to hold some number of mpz_t array
} CoolArray;

Allocation strategy, knowing the the number of values and bit-depth, would be:

CoolArray* allocArray(size_t length, size_t numbits)
{
   CoolArray *p = malloc(sizeof(*p) + sizeof(mpz_t)*length);
   p->length = length;
   p->numbits = numbits;
   mpz_array_init(p->vals, length, numbits);
   return p;
}

Freeing it (just a wrapper for free(), but you may need to do some gmp-cleanup I'm unfamiliar with):

void freeArray(CoolArray **pp)
{
    if (*pp)
    {
        free(*pp);
        *pp = NULL;
    }
}

Using it:

CoolArray *pca = allocArray(length, numbits);

Freeing it when done:

freeArray(&pca);

These are just ideas, but maybe you can get something from them.

Upvotes: 3

Related Questions