指向 mpz_t 数组的指针出现双重释放错误
我目前正在学习 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’
无论如何,我的问题是:
- 我确信我应该在 mpz_init_set_ui() 调用中取消引用指针,为什么这是错误的?
- 有更好的方法吗?我应该使用链表吗?(我还没有学过链表,我认为数组最适合这个,但如果我真的让事情变得更加困难,请告诉我) 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;
}
提前感谢大家,
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\n", 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:
- I'm sure I should be dereferencing the pointer in the mpz_init_set_ui() call, why is that wrong?
- 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,
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这条线
可能是您遇到麻烦的原因。您已为指向
mpz_t
的 5 个指针分配了足够的空间,而不是 5 个mpz_t
。根据 mpz_t 的大小,您可能会写到数组末尾,等等。您会想说
分配一个包含 5 个 mpz_t 的数组。
This line
is likely the cause of your troubles. You've allocated enough space for five pointers to
mpz_t
s, not for 5mpz_t
s. Depending on the size of an mpz_t, you could be writing past the end of the array, etc.You'll want to say
to allocate an array of 5 mpz_t's.
你的问题的一部分
p
是一个指向mpz_t
的指针;p[0]
(与*p
相同)是一个mpz_t
,p[1]
也是一个mpz_t
(相同如*(p + 1)
), ...p[1]
是mpz_t
。你不能取消引用它(我认为)。如果您愿意,可以使用以下语法
Just part of your question
p
is apointer to mpz_t
;p[0]
(same as*p
) is ampz_t
, as isp[1]
(same as*(p + 1)
), ...p[1]
is ampz_t
. You cannot dereference it (I think).You can use the following syntax if you prefer