English 中文(简体)
double free error with pointer to array of mpz_t
原标题:

I m currently learning libgmp and to that end I m writing a small program which find prime factors. My program calls a function which fills an array with a varying amount of mpz_t integers, prime factors of a given number, which I need to return. I m planning on setting the last element to NULL, so I know how many mpz_t integers the function found.

My problem is I m getting double free errors with my array of pointers to mpz_t integers. I ve written up some sample code illustrating my problem:

#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
", p[0], p[1]);
    mpz_clear(p[0]);
    mpz_clear(p[1]);
    free(p);
    return 0;
}

2 and 5 are printed to stdout, so allocation seems to be fine. But I m getting the double free error below:

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]

I m still getting totally used to pointers, and gcc gives no errors, however I m fairly sure this is wrong and I should be doing something like

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

instead of:

mpz_init_set_ui(p[0], 2UL);

But that gives me a compiler error

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’

Anyway, my questions are:

  1. I m sure I should be dereferencing the pointer in the mpz_init_set_ui() call, why is that wrong?
  2. Is there a better way of doing this? Should I use a linked list?(I ve not learned linked lists yet, I figure an array is best for this but if I m really making things way more difficult, tell me) 3.Would it be better to create a struct with a pointer to my array and another variable with the amount of elements in my array and return a pointer to that instead?

The platform is linux 32-bit just in case that s relevant.

Here is the code I have just now, which I want to modify, I declare the array of mpz_t on the stack. But I want to make main() a function:

#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;
}

Thanks in advance people,

最佳回答

This line

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

is likely the cause of your troubles. You ve allocated enough space for five pointers to mpz_ts, not for 5 mpz_ts. Depending on the size of an mpz_t, you could be writing past the end of the array, etc.

You ll want to say

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

to allocate an array of 5 mpz_t s.

问题回答

Just part of your question

mpz_t *p = ...;

p is a pointer to mpz_t; p[0] (same as *p) is a mpz_t, as is p[1] (same as *(p + 1)), ...

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

p[1] is a mpz_t. You cannot dereference it (I think).
You can use the following syntax if you prefer

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




相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...

热门标签