I'm trying to implement a linked list which holds one rational GMP array mpq_t
as its data, furthermore I want it to hold the length to end of the current linked list lte
and for convenience the length of the array n
.
To test it I generate arbitrary mpq_t
arrays and feed it into my GMPlist_push
function which is meant to just create a new node holding the array.
The code below works, however either I have forgotten something trivial or there is a problem with my GMP installation. When I run it, it's supposed to stream out 5 random numbers and then tell me in which node it is, however on my MacBook it goes 1, 4294967297, 4294967298, 4294967297 and then it continues to oscillate between the two, when I run the exact same code on my Debian desktop it does the desired 1,2,3...
This seems like 'unpredictable' behaviour which on the Linux machine seems to work in my favour and it doesn't on my Mac. Can you see something I forgot? Also can you reproduce an erroneous behaviour?
It might be noteworthy that although the executable runs without error lldb crashes with obscure malloc errors.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <gmp.h>
#include <assert.h>
struct GMPlist {
mpq_t* data;
size_t n, lte;
struct GMPlist* next;
};
typedef struct GMPlist GMPlist;
mpq_t *randomVector(size_t n){
mpq_t* retVal;
retVal = malloc(n*sizeof(*retVal));
size_t i;
size_t den,num;
for (i = 0; i < n; i++){
mpq_init(retVal[i]);
den = (size_t)rand();
num = (size_t)rand();
mpq_set_ui(retVal[i],den,num);
mpq_canonicalize(retVal[i]);
}
return retVal;
}
void GMPlist_push(GMPlist** elem, mpq_t* data){
GMPlist* nextElem = malloc(sizeof(GMPlist*));
nextElem->next = *elem;
nextElem->lte = (*elem)->lte + 1;
nextElem->n = (*elem)->n;
nextElem->data = data;
*elem = nextElem;
}
int main(int argc, char const *argv[])
{
GMPlist* elem = malloc(sizeof(GMPlist));
srand(time(NULL));
elem->next = NULL;
elem->lte = 0;
elem->n = 5;
mpq_t* tester;
size_t i,j;
for (j = 0; j<10; j++){
tester = randomVector(5);
GMPlist_push(&elem, tester);
for (i=0; i<5; i++){
mpq_out_str(stdout,10,elem->data[i]);
fprintf(stdout, " ");
}
fprintf(stdout, ", %lu\n", elem->lte );
}
return 0;
}
Thank you, Rainer
In GMPlist_push
, you're not allocating the proper amount of memory:
GMPlist* nextElem = malloc(sizeof(GMPlist*));
You want the size of a GMPlist
, but you're getting the size of a GMPlist *
, which is smaller.
Do this instead:
GMPlist* nextElem = malloc(sizeof(GMPlist));
If you run the code under valgrind, it will show you where you're reading/writing memory you're not supposed to.