2012-10-25 6 views
2

이전에 필자는 필자가 작성한 파스칼 삼각형 프로그램에 대한 질문을하고 초기 문제를 수정했습니다. gmp로이 작업을 시도해 보니 새로운 문제가 생겼습니다! 나는 언어에 익숙하지 않으므로 나와 양육하십시오. 여기pascals 삼각형 모양의 c와 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); 

?

첫 번째는 매뉴얼에서 직접 나온 예제이고 두 번째는 코드에서 어떻게 작성한 것입니까? 나는 그것이 문제일지도 모른다라고 생각한다. 그러나 나는 2가 다를 것 인 이유를 모른다.

답변

0

sizeof(mpz_t)size_t입니다. 많은 현대 시스템에서 size_tint으로 정의되지 않습니다. 구조체 필드를 size_t numbits으로 선언해야합니다.

+0

감사합니다. 컴파일러가 경고 한 고정 된 한 가지가 있지만 여전히 malloc 오류가 발생했습니다. 나는 그 문제가 무엇인지 압니다. – Broseph