我是一名经验丰富的程序员,但对C新手。我正在尝试学习C所以我可以使用gmp库来编写快速的大整数程序;最后我打算用C函数编写我的程序的性能部分,这些函数通过其他语言的外部函数接口调用。作为学习C和gmp库的工具,我编写了如下所示的pollard rho整数分解程序(是的,我知道这不是pollard rho最好的实现,但它很简单,而且此刻我只是想要开始)。我的程序编译正确,但运行时它会消息“分段错误”。我认为这意味着我的指针搞砸了,但我没有看到它。可能不止一个。有人可以看看我的节目并告诉我哪里出错了?并指出任何风格问题或我可以改进的任何其他事项?非常感谢,菲尔
/* rho.c -- pollard rho factorization
* usage: rho n -- prints factors of n then exits
* compile as gcc -lgmp -o rho rho.c */
#include <stdlib.h>
#include <stdio.h>
#include <gmp.h>
typedef struct list {
void *data;
struct list *next;
} List;
List *insert(void *data, List *next)
{
List *new;
if (! (new = malloc(sizeof(List))))
return NULL;
new->data = data;
new->next = next;
return new;
}
List *insert_in_order(void *x, List *xs)
{
if (xs == NULL || mpz_cmp(x, xs->data) < 0)
{
return insert(x, xs);
} else {
List *head = xs;
while (xs->next != NULL && mpz_cmp(x, xs->next->data) < 0)
{
xs = xs->next;
}
xs->next = insert(x, xs->next);
return head;
}
}
void rho_factor(mpz_t f, mpz_t n, long long unsigned c)
{
mpz_t t, h, d, r;
mpz_init_set_ui(t, 2);
mpz_init_set_ui(h, 2);
mpz_init_set_ui(d, 1);
mpz_init_set_ui(r, 0);
while (mpz_cmp_si(d, 1) == 0)
{
mpz_mul(t, t, t);
mpz_add_ui(t, t, c);
mpz_mod(t, t, n);
mpz_mul(h, h, h);
mpz_add_ui(h, h, c);
mpz_mod(h, h, n);
mpz_mul(h, h, h);
mpz_add_ui(h, h, c);
mpz_mod(h, h, n);
mpz_sub(r, t, h);
mpz_gcd(d, r, n);
}
if (mpz_cmp(d, n) == 0)
{
rho_factor(f, n, c+1);
}
else if (mpz_probab_prime_p(d, 25))
{
mpz_set(f, d);
}
else
{
rho_factor(f, d, c+1);
}
mpz_clears(t, h, d, r);
}
void rho_factors(List *fs, mpz_t n)
{
mpz_t f;
mpz_init_set_ui(f, 0);
while (! (mpz_probab_prime_p(n, 25)))
{
rho_factor(f, n, 1);
fs = insert_in_order(f, fs);
mpz_divexact(n, n, f);
}
mpz_clear(f);
insert_in_order(n, fs);
}
int main(int argc, char *argv[])
{
mpz_t f, n;
mpz_init_set_ui(f, 0);
List *fs = NULL;
if (argc<2)
{
printf("usage: rho n\n");
return 1;
}
mpz_init_set_str(n, argv[1], 10);
if (mpz_probab_prime_p(n, 25))
{
printf("%s\n", argv[1]);
return 0;
}
printf("%s", argv[1]);
rho_factors(fs, n);
while (fs != NULL) {
printf(" %s", mpz_get_str(NULL, 10, fs->data));
fs = fs->next;
}
return 0;
}
EDIT1:感谢Daniel Fischer,我取得了一些进展,不再遇到分段错误。当使用n = 1234567调用rho_factor时,下面显示的代码正确打印因子127,但是rho_factors返回空列表,因此rho_factors仍然存在问题。我认为问题是我无法按照我的方式继续重新初始化相同的变量,但我不知道正确的方法。不知怎的,我需要复制我找到的每个因素,然后在fs中插入该副本。非常感谢,菲尔
/* rho.c -- pollard rho factorization
* usage: rho n -- prints factors of n then exits
* compile as gcc -lgmp -o rho rho.c */
#include <stdlib.h>
#include <stdio.h>
#include <gmp.h>
typedef struct list {
void *data;
struct list *next;
} List;
List *insert(void *data, List *next)
{
List *new;
if (! (new = malloc(sizeof(List))))
return NULL;
new->data = data;
new->next = next;
return new;
List *insert_in_order(void *x, List *xs)
{
if (xs == NULL || mpz_cmp(x, xs->data) < 0)
{
return insert(x, xs);
} else {
List *head = xs;
while (xs->next != NULL && mpz_cmp(x, xs->next->data) < 0)
{
xs = xs->next;
}
xs->next = insert(x, xs->next);
return head;
}
}
void rho_factor(mpz_t f, mpz_t n, long long unsigned c)
{
mpz_t t, h, d, r;
mpz_init_set_ui(t, 2);
mpz_init_set_ui(h, 2);
mpz_init_set_ui(d, 1);
mpz_init_set_ui(r, 0);
while (mpz_cmp_si(d, 1) == 0)
{
mpz_mul(t, t, t);
mpz_add_ui(t, t, c);
mpz_mod(t, t, n);
mpz_mul(h, h, h);
mpz_add_ui(h, h, c);
mpz_mod(h, h, n);
mpz_mul(h, h, h);
mpz_add_ui(h, h, c);
mpz_mod(h, h, n);
mpz_sub(r, t, h);
mpz_gcd(d, r, n);
}
if (mpz_cmp(d, n) == 0)
{
rho_factor(f, n, c+1);
}
else if (mpz_probab_prime_p(d, 25))
{
mpz_set(f, d);
}
else
{
rho_factor(f, d, c+1);
}
mpz_clears(t, h, d, r, NULL);
}
void rho_factors(List *fs, mpz_t n)
{
while (! (mpz_probab_prime_p(n, 25)))
{
mpz_t f;
mpz_init_set_ui(f, 0);
rho_factor(f, n, 1);
fs = insert_in_order(f, fs);
mpz_divexact(n, n, f);
}
insert_in_order(n, fs);
}
int main(int argc, char *argv[])
{
mpz_t f, n;
mpz_init_set_ui(f, 0);
List *fs = NULL;
if (argc<2)
{
printf("usage: rho n\n");
return 1;
}
mpz_init_set_str(n, argv[1], 10);
if (mpz_probab_prime_p(n, 25))
{
printf("%s is prime\n", argv[1]);
return 0;
}
rho_factor(f, n, 1);
printf("%s\n", mpz_get_str(NULL, 10, f));
printf("%s", argv[1]);
rho_factors(fs, n);
while (fs != NULL) {
printf(" %s", mpz_get_str(NULL, 10, fs->data));
fs = fs->next;
}
return 0;
}
EDIT2:明白了。感谢Daniel Fischer。最终版本如下所示。
/* rho.c -- pollard rho factorization
* usage: rho n -- prints factors of n then exits
* compile as gcc -lgmp -o rho rho.c */
#include <stdlib.h>
#include <stdio.h>
#include <gmp.h>
typedef struct list {
void *data;
struct list *next;
} List;
List *insert(void *data, List *next)
{
List *new;
new = malloc(sizeof(List));
new->data = data;
new->next = next;
return new;
}
List *insert_in_order(void *x, List *xs)
{
if (xs == NULL || mpz_cmp(x, xs->data) < 0)
{
return insert(x, xs);
}
else
{
List *head = xs;
while (xs->next != NULL && mpz_cmp(x, xs->next->data) < 0)
{
xs = xs->next;
}
xs->next = insert(x, xs->next);
return head;
}
}
void rho_factor(mpz_t f, mpz_t n, long long unsigned c)
{
mpz_t t, h, d, r;
mpz_init_set_ui(t, 2);
mpz_init_set_ui(h, 2);
mpz_init_set_ui(d, 1);
mpz_init_set_ui(r, 0);
while (mpz_cmp_si(d, 1) == 0)
{
mpz_mul(t, t, t);
mpz_add_ui(t, t, c);
mpz_mod(t, t, n);
mpz_mul(h, h, h);
mpz_add_ui(h, h, c);
mpz_mod(h, h, n);
mpz_mul(h, h, h);
mpz_add_ui(h, h, c);
mpz_mod(h, h, n);
mpz_sub(r, t, h);
mpz_gcd(d, r, n);
}
if (mpz_cmp(d, n) == 0)
{
rho_factor(f, n, c+1);
}
else if (mpz_probab_prime_p(d, 25))
{
mpz_set(f, d);
}
else
{
rho_factor(f, d, c+1);
}
mpz_clears(t, h, d, r, NULL);
}
void rho_factors(List **fs, mpz_t n)
{
while (! (mpz_probab_prime_p(n, 25)))
{
mpz_t *f = malloc(sizeof(*f));
mpz_init_set_ui(*f, 0);
rho_factor(*f, n, 1);
*fs = insert_in_order(*f, *fs);
mpz_divexact(n, n, *f);
}
*fs = insert_in_order(n, *fs);
}
int main(int argc, char *argv[])
{
mpz_t f, n;
mpz_init_set_ui(f, 0);
List *fs = NULL;
if (argc<2)
{
printf("usage: rho n\n");
return 1;
}
mpz_init_set_str(n, argv[1], 10);
if (mpz_probab_prime_p(n, 25))
{
printf("%s is prime\n", argv[1]);
return 0;
}
printf("Factors of %s:", argv[1]);
rho_factors(&fs, n);
while (fs != NULL) {
printf(" %s", mpz_get_str(NULL, 10, fs->data));
fs = fs->next;
}
printf("\n");
return 0;
}
答案 0 :(得分:3)
您无法重复使用mpz_t
:
void rho_factors(List *fs, mpz_t n)
{
mpz_t f;
mpz_init_set_ui(f, 0);
while (! (mpz_probab_prime_p(n, 25)))
{
rho_factor(f, n, 1);
fs = insert_in_order(f, fs);
mpz_divexact(n, n, f);
}
mpz_clear(f);
insert_in_order(n, fs);
}
当GMP重新分配通过f
指向的存储时,旧存储为free
d。这可能发生在while循环中,但不一定。如果没有,则所有列表条目都指向相同的数字。
但是在循环之后,当您mpz_clear(f)
时,列表data
中的每个fs
指针都变成了一个狂野指针,然后当您insert_in_order(n, fs)
时,您之前取消引用free
指针。 (这可能在while循环中的某些插入期间已经发生,但在这里它是有保证的。)
此外,在rho_factor
中,您应该致电
mpz_clears(t, h, d, r, NULL);
mpz_clears
的参数列表必须为NULL
- 已终止。
其他问题:
List *
,因此对fs
中的rho_factors
所做的更改不会影响fs
中的main
。传递List **
并在适当的位置取消引用,您也忘记分配最终insert_in_order
的返回值。本地变量f
在块结束时超出范围,导致损坏。 malloc
mpz_t
指向 rho_factor(*f, n, 1);
*fs = insert_in_order(*f, *fs);
mpz_divexact(n, n, *f);
}
*fs = insert_in_order(n, *fs);
以保持活着。
void rho_factors(List ** fs,mpz_t n) { while(!(mpz_probab_prime_p(n,25))) { mpz_t * f = malloc(sizeof(* f)); mpz_init_set_ui(* f,0);
main
}
并在List *fs = NULL;
/* snip */
rho_factors(&fs, n);
insert_in_order
应该这样做。最后(?),你在{{1}}中有一个小故障,while循环中的比较是向后的。