我使用两种不同的递归总和方法遇到问题,其中某个时候失败并返回分割故障错误。第一个,sum_a仅在高价值上失败,传递给了260000,我不知道为什么,第二个sum_b总是失败。任何帮助将不胜感激。
谢谢
执行如下:./sum a x
其中x是所需的递归数量(1:x(,a是a或b
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unsigned count=0;
void signal_segv_handler(int sig) {
char s[50];
sprintf(s, "Segmentation fault! count=%un", count);
write(2, s, strlen(s));
_exit(1);
}
unsigned long long *sum_b(unsigned long long x) {
unsigned long long *s;
count++;
if (x>0)
*s = *sum_b(x - 1) + x;
else
*s = 0;
return s;
}
unsigned long long sum_a(unsigned long long x) {
count++;
if (x>0)
return sum_a(x - 1) + x;
else
return 0;
}
int main(int argc, char** argv) {
unsigned long long x;
unsigned long long *sum_result;
char result[100];
static char stack[SIGSTKSZ];
stack_t ss = {
.ss_size = SIGSTKSZ,
.ss_sp = stack,
};
struct sigaction sa = {
.sa_handler = signal_segv_handler,
.sa_flags = SA_ONSTACK
};
sigaltstack(&ss, 0);
sigfillset(&sa.sa_mask);
sigaction(SIGSEGV, &sa, 0);
if (argc < 3) {
printf("Please specify the sum function to use (a or b) and the target number of integers to sum.n");
return -1;
}
x = atoi(argv[2]);
if (strcmp(argv[1], "a") == 0)
sprintf(result, "sum_a = %llu for x=%llu, count=%u n", sum_a(x), x, count);
else if (strcmp(argv[1], "b") == 0) {
sum_result = sum_b(x);
sprintf(result, "sum_b = %llu for x=%llu, count=%u n", sum_result, x, count);
free(sum_result);
}
else {
printf("error: function must be a or bn");
return -1;
}
write(1, result, strlen(result));
return 0;
}
unsigned long long *sum_b(unsigned long long x) {
unsigned long long *s; <------
count++;
if (x>0)
*s = *sum_b(x - 1) + x;
else
*s = 0;
return s;
}
您使用的是非初始化的指针,而没有任何MEM分配来存储总和结果。
sum_a和sum_b均导致堆栈溢出时,当它们的迭代消耗比堆栈中可用的更多内存时。看起来您程序的堆栈大小为8192KB(您可以使用ulimit -s
在控制台中检查它(,一个sum_a迭代消耗32个字节,而sum_b需要48个字节(因为变量多于sum_a -a -a - unsigned long long *s;
,并且可能16个Byte stack stack stack stack stack stack stack stack stack stack stack我不确定对齐(,因此它们分别在〜260K和〜170K迭代上堆叠堆栈。
但是sum_b有另一个segfault点,在这里 *s = *sum_b(x - 1) + x;
,在这里 *s = 0;
这将分配给非直接的指针(野生指针,指向随机内存地址(。如果没有发生任何堆栈溢出,就会发生这种情况(在这种情况下,从未达到分配操作(。
一些与问题无关的评论:
- 您在主堆栈上分配Alt堆栈,如果溢出的话,您的处理程序处于不良状态,它仍然可以在某些情况下工作,但是您应该将
static char stack[SIGSTKSZ];
更改为Malloc函数。 - 您应该避免在信号处理程序中不使用信号安全功能,这是您在信号安全人员中可能找到的功能列表。
- 这线可能没有必要,您可以将其删除
sigfillset(&sa.sa_mask);
- 另一个segfault:
free(sum_result);
您应该始终平衡malloc用免费电话。