5

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?

none
  • 11,793
  • 9
  • 51
  • 87
Broseph
  • 1,655
  • 1
  • 18
  • 38
  • I'm not sure about this so I'm putting it as a comment. Isn't mpz_t dynamically allocated? As in it'll be as large as required. So making an array of mpz_t wouldn't work because they're always changing size depending on the input. – Guillaume Oct 25 '12 at 18:11
  • @Enders: `mpz_array_init` will dynamically allocate size for the numbers, but then they will not be allowed to grow afterwards. See [LibGMP Documentation](http://gmplib.org/manual/Integer-Special-Functions.html). – Dietrich Epp Oct 25 '12 at 18:25

2 Answers2

3

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.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • Note: `memset` is redundant with `mpz_array_init`. – Dietrich Epp Oct 25 '12 at 18:26
  • @DietrichEpp Not surprised by that. Like I said, not familiar with gmp, but have done plenty of tail-based dynamic buffers on structs. Thanks for the info, I'll remember that if i ever do pick up gmp for something. – WhozCraig Oct 25 '12 at 18:28
  • It's not actually GMP-specific -- it's a relatively common naming convention for `something_init` functions to initialize existing memory, paired with `something_destroy`; just like `something_new` gets paired with `something_free`. – Dietrich Epp Oct 25 '12 at 18:30
  • 1
    @DietrichEpp As much as I've used OpenSSL and BSAFE CryptoCME, you'd think I would have picked up on that. Again, thanks. – WhozCraig Oct 25 '12 at 18:36
0

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);
ecatmur
  • 152,476
  • 27
  • 293
  • 366