【问题标题】:double free error with pointer to array of mpz_t指向 mpz_t 数组的指针的双重释放错误
【发布时间】:2009-12-12 02:49:34
【问题描述】:

我目前正在学习 libgmp,为此我正在编写一个小程序来寻找主要因素。我的程序调用了一个函数,它用不同数量的 mpz_t 整数填充数组,给定数字的素数,我需要返回。我打算将最后一个元素设置为 NULL,所以我知道函数找到了多少个 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]

我仍然完全习惯了指针,并且 gcc 没有给出任何错误,但是我很确定这是错误的,我应该做类似的事情

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.用指向我的数组的指针和另一个包含数组中元素数量的变量创建一个结构并返回一个指向它的指针会更好吗?

平台是 linux 32 位,以防万一。

这是我刚才的代码,我要修改,我在堆栈上声明了mpz_t的数组。但我想让 main() 成为一个函数:

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

提前感谢大家,

【问题讨论】:

  • 你能把剩下的代码贴出来吗?

标签: c pointers malloc gmp double-free


【解决方案1】:

这一行

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

很可能是您遇到麻烦的原因。您已经为mpz_ts 的五个指针分配了足够的空间,而不是为5 个mpz_ts。根据 mpz_t 的大小,你可能会写到数组的末尾,等等。

你会想说

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

分配一个包含 5 个 mpz_t 的数组。

【讨论】:

  • 我喜欢使用对象本身作为 sizeof 的参数:mpz_t *p = malloc(5 * sizeof p); :-)
  • pmg,我愿意,除非你的意思是sizeof *p,否则你和OP有同样的问题;)
  • 我会记住的,我从来没有使用过这个对象。代码的复杂程度总是让我感到惊讶,但语法却非常小。非常感谢大家!
【解决方案2】:

只是你问题的一部分

mpz_t *p = ...;

p 是一个pointer to mpz_tp[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);

【讨论】:

    猜你喜欢
    • 2014-06-22
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-23
    • 2016-07-18
    • 2021-08-17
    相关资源
    最近更新 更多