2

gmpでこれをやろうとしたときに問題があります。

/*
  This code is just to see exactly how much faster C is than python
  at doing numerically stuff. It should calculate the nth row of 
  pascals triangle.
  The way you use it is by calling the executable with the row
  you wish to compute as the only argument. For example if you 
  are on an *nix system:
  ./pascal 6 

  Or in a windows command prompt:
  pascal.exe 6
*/

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <gmp.h>

/*
  I decided to use a struct here because I thought it was ugly
  to have to pass around the length of my arrays in function 
  calls.
*/

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

//initArray allocates memory for the CoolArray.
void initArray(CoolArray* array, int length, int numbits); 

//destroyArray frees allocated memory in the struct.
void destroyArray(CoolArray* array);

//printArray prints the contents of the array.
void printArray(CoolArray* array);

//pascal computes the nth row of pascal's 
//triangle, with n being array->length,
//and stores the values in the array.
void pascal(CoolArray* array);

//setArray takes two CoolArrays of the same length
//and sets the values in the first to the values
//in the second.
void setArray(CoolArray* array1, CoolArray* array2);

int main(int argc, char** argv){
  int length = atoi(argv[1]);
  CoolArray array1;
  initArray(&array1, length, 800); //giving every int 800 bits of memory
  printf("Calculating the %dth row of pascals triangle...\n", length);
  pascal(&array1);
  printArray(&array1);
  destroyArray(&array1);
  return 0;
}

void initArray(CoolArray* array, int length, int numbits){
  assert(length>=1); //don't make arrays with a length <=0!!!
  array->length = length;
  array->vals = (mpz_t*) calloc(length, sizeof(mpz_t)); //first I allocate memory for vals...
  mpz_array_init(array->vals, length, numbits); //then I allocate memory for each val in vals
  return;
}

void destroyArray(CoolArray* array){
  int i=0;
  for(; i < array->length; ++i){ //first I go through the array and 
    mpz_clear(array->vals[i]); //clear the memory used for each val
  }
  free(array->vals); //then use free on the entire array
  return;
}

void pascal(CoolArray* array){
  assert(array->length >= 1);//making sure the length wasn't fiddled with...

  if(array->length == 1){
    mpz_set_ui(array->vals[0], (unsigned long int)1);
    return;
  }
  int row;
  int index;
  mpz_set_ui(array->vals[0], (unsigned long int)1); //if we aren't looking for the first row
  mpz_set_ui(array->vals[1], (unsigned long int)1);//then i'll start with the second row
  CoolArray current;
  initArray(&current, array->length, array->numbits); //current is a helper array
  for(row = 2; row < array->length; ++row){
    mpz_set_ui(current.vals[0], (unsigned long int)1); //set the first val to 1
    for(index = 1; index < row; ++index){
      mpz_add(current.vals[index], //set the value of this...
          array->vals[index],  //to this...
          array->vals[index-1]); //plus this.
    }
    mpz_set_ui(current.vals[row], (unsigned long int)1); //make the last number 1
    //printArray(&current);
    setArray(array, &current); //put every value in current into array
  }
  destroyArray(&current); //get rid of current
  return;
}

void setArray(CoolArray* array1, CoolArray* array2){
  assert(array1->length==array2->length);//making sure they are the same length
  int i=0;
  for(; i < array2->length; ++i){
    mpz_set(array1->vals[i], array2->vals[i]); //array1 is the array whose values are being set
  }
  return;
}

void printArray(CoolArray* array){
  int i=0;
  printf("[");
  for(; i < array->length; ++i){
    mpz_out_str(stdout, 10, array->vals[i]);
    if(i < (array->length - 1)) printf(", ");
    else printf("]\n");
  }
  return;
}

私は正しい出力を得ています。印刷された値は正しいですが、期待される出力とともに、ターミナルで次のような行も取得しています。

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

関数で間違ってメモリを解放していますdestroyArrayか? もしそうなら、私が知る限り(gmpマニュアルをチェックすることから)、これを正しく行っているので、それを修正するために何ができますか。それとも、gmp のインストールに問題がありますか?

編集:さて、 mpz_t 配列の各要素へのポインターを mpz_clear に渡していることに気付いたとき、mpz_t 自体を渡す必要があったときに、主な問題を見つけたと思いましたプログラムを実行すると、まだ上記の出力が得られます。しかし、私はまだこのコンパイラ警告を持っています:

gmpascal.c: In function ‘initArray’:
gmpascal.c:62: warning: passing argument 1 of ‘__gmpz_array_init’ from incompatible pointer type

これは:

mpz_t array[length]; //length is an int
mpz_array_init(array, length, numbits); //and so is numbits

これとは異なります:

mpz_t* array;
array = (mpz_t*) calloc(length, sizeof(mpz_t));
mpz_array_init(array, length, numbits);

?

1 つ目はマニュアルからの直接の例で、2 つ目は自分のコードでどのように記述したかです。それが問題かもしれないと思いますが、なぜ2つが違うのかわかりません。

4

2 に答える 2

0

sizeof(mpz_t)タイプsize_tです。多くの最新システムでsize_tは、 は として定義されていませんint。構造体フィールドを として宣言する必要がありますsize_t numbits

于 2012-10-25T12:46:20.950 に答える