2009-12-12 5 views
1

В настоящее время я изучаю libgmp, и с этой целью я пишу небольшую программу, которая находит простые факторы. Моя программа вызывает функцию, которая заполняет массив с различным количеством mpz_t целых чисел, простых факторов заданного числа, которые мне нужно вернуть. Я планирую установить последний элемент в NULL, поэтому я знаю, сколько целых чисел mpz_t обнаружено.двойная бесплатная ошибка с указателем на массив mpz_t

Моя проблема: я получаю двойные бесплатные ошибки с моим массивом указателей на целые числа mpz_t. Я написал некоторый пример кода, иллюстрирующий мою проблему:

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

int main(void) 
{ 
    mpz_t *p = malloc(5*sizeof(mpz_t*)); 
    mpz_init_set_ui(p[0], 2UL); 
    mpz_init_set_ui(p[1], 5UL); 
    gmp_printf("%Zd %Zd\n", p[0], p[1]); 
    mpz_clear(p[0]); 
    mpz_clear(p[1]); 
    free(p); 
    return 0; 
} 

2 и 5 печатаются на стандартный вывод, поэтому распределение, кажется, хорошо. Но я получаю двойную бесплатно ошибку ниже:

2 5 
*** glibc detected *** ./lol: double free or corruption (out): 0x08e20020 *** 
======= Backtrace: ========= 
/lib/libc.so.6(+0x6b6c1)[0xb77126c1] 
/lib/libc.so.6(+0x6cf18)[0xb7713f18] 
/lib/libc.so.6(cfree+0x6d)[0xb7716f8d] 
/usr/lib/libgmp.so.3(__gmp_default_free+0x1d)[0xb77f53fd] 
/usr/lib/libgmp.so.3(__gmpz_clear+0x2c)[0xb77ff08c] 
./lol[0x80485e3] 
/lib/libc.so.6(__libc_start_main+0xe6)[0xb76bdb86] 
./lol[0x80484e1] 

Я все еще полностью используется для указателей, и НКУ не дает никаких ошибок, но я абсолютно уверен, что это неправильно, и я должен делать что-то вроде

mpz_init_set_ui(*p[0], 2UL); 

вместо:

mpz_init_set_ui(p[0], 2UL); 

Но это дает мне ошибку компилятора

test.c:8: error: incompatible type for argument 1 of ‘__gmpz_init_set_ui’ 
/usr/include/gmp.h:925: note: expected ‘mpz_ptr’ but argument is of type ‘__mpz_struct’ 

Во всяком случае, мои вопросы:

  1. Я уверен, что я должен быть разыменования указателя в mpz_init_set_ui вызова(), почему это так?
  2. Есть ли лучший способ сделать это? Должен ли я использовать связанный список? (Я еще не изучил связанные списки, я считаю, что массив лучше всего подходит для этого, но если я действительно затрудняю ситуацию, скажите мне) 3. Было бы лучше создать struct с указателем на мой массив и другую переменную с количеством элементов в моем массиве и вместо этого вернуть указатель на это?

Платформа - это 32-разрядная версия Linux на всякий случай.

Вот код, который у меня есть сейчас, который я хочу изменить, объявляю массив mpz_t в стеке. Но я хочу сделать основной() функцию:

#include <stdio.h> 
#include <stdlib.h> 
#include "prime.h" 

#define MAXFACTORS 100 

int main(void) 
{ 
    mpz_t numToFactor, factor; 
    mpz_t result;/* used to pass return values from getPrimeFactor() */ 
    mpz_t primeFactors[MAXFACTORS]; 

    mpz_init_set_str(numToFactor, "18 446 744 073 709 551 615 436 457 568", 10); 
    mpz_init(factor); 
    mpz_init(result); 

    int pFLen = 0; 
    mpz_init(primeFactors[pFLen]); 

    getPrimeFactor(numToFactor, result); 
    mpz_set(factor, result); 
    while(mpz_cmp_ui(factor, 0UL)) 
    { 
     mpz_set(primeFactors[pFLen], factor); 
     pFLen++; 
     if(pFLen == MAXFACTORS) 
     { 
      puts("Ran out of space to store prime factors, quitting..."); 
     } 
     mpz_init(primeFactors[pFLen]); 

     mpz_divexact(factor, numToFactor, factor); 
     mpz_set(numToFactor, factor); 

     getPrimeFactor(factor, result); 
     mpz_set(factor, result); 
    } 
    mpz_set(primeFactors[pFLen], numToFactor); 
    pFLen++; 

    int i; 
    for(i = 0; i < pFLen; i++) 
    { 
     gmp_printf("%Zd ", primeFactors[i]); 
    } 
    puts(""); 

    mpz_clear(numToFactor); 
    mpz_clear(factor); 
    return 0; 
} 

Заранее спасибо людям,

+0

могли бы вы опубликовать остальную часть кода? –

ответ

3

Эта линия

mpz_t *p = malloc(5*sizeof(mpz_t*)); 

, скорее всего, причиной ваших неприятностей. Вы выделили достаточно места для пяти указателей до mpz_t s, а не для 5 mpz_t s. В зависимости от размера в mpz_t, вы могли бы писать мимо конца массива и т.д.

Вы хотите сказать,

mpz_t *p = malloc(5*sizeof(mpz_t)); 

выделить массив из 5 mpz_t годов.

+1

Мне нравится использовать сам объект для аргумента sizeof: 'mpz_t * p = malloc (5 * sizeof p);' :-) – pmg

+3

pmg, я делаю, за исключением того, что вы имеете в виду 'sizeof * p' здесь, иначе у вас такая же проблема, как у OP;) –

+0

Я запомню, что никогда не использовал этот объект. Никогда не перестаешь удивлять меня, как сложный код, но синтаксис довольно мал. Спасибо всем! – CalumMcCall

2

Просто часть вашего вопроса

mpz_t *p = ...; 

p является pointer to mpz_t; p[0] (такой же, как *p) является mpz_t, как p[1] (так же, как *(p + 1)), ...

mpz_init_set_ui(*p[1], 5UL); /* error */ 

p[1] является mpz_t. Вы не можете разыгрывать его (я думаю).
Вы можете использовать следующий синтаксис, если вы предпочитаете

mpz_init_set_ui(*(p + 1), 5UL);