将数组元素传递给 Pascal 循环中的递归函数时的 SigSegv
SigSegv when passing array element to a recursive function in a loop in Pascal
所以在这个程序中,我们创建了一个数组 Tab1,其 10 个元素具有随机值,然后我们获取每个 Tab1 元素的阶乘并将其放入 Tab2,使用迭代和递归两种方法。当使用迭代函数时,Tab2 充满阶乘没有问题,但当我使用递归函数时,程序立即退出。如果你能帮助我深入理解这个问题,我将不胜感激......我在维基百科上读到了分段错误,它说这是因为程序试图到达它没有权限的内存位置输入,但问题是当我从 Tab1 选择一个特殊元素时,例如 Tab1[5] 并将其传递给 Calc2 中的 factorielleRecursive 它工作得很好,有什么想法吗?
Program recursive;
Type
T = array [1..10] of LongInt;
Var
Tab1, Tab2 : T;
num : integer;
Function FactorielleIterative(N : integer) : integer;
Var
F, i : integer;
Begin
F := 1;
for i:=1 to N Do
F := F*i;
FactorielleIterative := F;
End;
Function FactorielleRecursive(N : LongInt) : LongInt;
Begin
if (N=1) Then
FactorielleRecursive := 1
Else
FactorielleRecursive := N * FactorielleRecursive(N-1);
End;
Procedure Fill(var Tab : T);
Var
i : Integer;
Begin
Randomize;
For i:=1 to 10 Do
Begin
Tab[i] := Random(10);
End;
For i:=1 to 10 Do
Write('[', Tab[i], '] ');
End;
Procedure Calc1(Tab1 : T; var Tab2 : T);
Var
i : integer;
Begin
For i:=1 to 10 Do
Begin
Tab2[i] := FactorielleIterative(Tab1[i]);
End;
For i:=1 to 10 Do
Write('[', Tab2[i], '] ');
End;
Procedure Calc2(Tab : T; var Tab2 : T);
Var
i : integer;
Begin
For i:=1 to 10 Do
Begin
Tab2[i] := FactorielleRecursive(Tab[i]);
End;
For i:=1 to 10 Do
Write('[', Tab2[i], '] ');
End;
Begin
Write('Tab1 : ');
Writeln;
Fill(Tab1);
Writeln;
Writeln;
Write('Tab2 : Iterative method');
Writeln;
Calc1(Tab1, Tab2);
Writeln;
Writeln;
Write('Tab2 : Recursive method');
Writeln;
Calc2(Tab1, Tab2);
Readln;
End.
我的想法:
- 我无法在我的设置中重现此问题:
bash$ fpc so.pas && ./so
Free Pascal Compiler version 3.2.0+dfsg-12 [2021/01/25] for x86_64
Copyright (c) 1993-2020 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling so.pas
so.pas(6,1) Note: Local variable "num" not used
Linking so
76 lines compiled, 0.1 sec
1 note(s) issued
注意:应删除未使用的变量。
您能否提供有关您的编译器及其编译时选项以及您的 OS 的更多详细信息?
Tab1[5]
只是一个随机值:它将 运行 更改为 运行。你是如何用它来验证的?你知道它现在的价值是多少吗?我从主块调用 FactorielleRecursive(10);
并且我没有遇到任何问题。此问题在您的 运行 时间环境中是间歇性的吗?
您的迭代函数只获取和 returns Integer
。我认为您应该像递归方式那样将 return 类型更改为 LongInt
。这里是两个版本之间的 运行 时间差(有一些溢出:见负值):
Tab2 : Iterative method
[5040]
[720]
[2]
[1]
[720]
[5040]
[24]
[1]
[-25216] <<<<<<<<<<<<<<<<< Integer overflow
[24]
Tab2 : Recursive method
[5040]
[720]
[2]
[1]
[720]
[5040]
[24]
[1]
[40320]
[24]
次要注意事项:
- 您可以将重复的代码部分提取到一个 procedure/function 中。在这种情况下,
for
循环重复 3 次以写出 Tab 数组的内容。
- 您可以将
Write
和 WriteLn
合并为一个语句。例如 WriteLn('Tab2 : Iterative method');
- 它是一种更紧凑的形式。
您没有考虑如果 Tab[]
数组包含零值会发生什么。这种情况是可能的,因为您调用 Random(10)
将 return 范围为 0 .. 9.
的值
在 Function FactorielleIterative()
中,零参数被视为“1”值(因为 for
循环未执行)。
在 Function FactorielleRecursive()
中,零参数被视为“0”值,递归调用的结果 FactorielleRecursive(N-1);
导致范围溢出。
解决方法很简单,所以我把它留给你来解决,以免破坏你的作业。
所以在这个程序中,我们创建了一个数组 Tab1,其 10 个元素具有随机值,然后我们获取每个 Tab1 元素的阶乘并将其放入 Tab2,使用迭代和递归两种方法。当使用迭代函数时,Tab2 充满阶乘没有问题,但当我使用递归函数时,程序立即退出。如果你能帮助我深入理解这个问题,我将不胜感激......我在维基百科上读到了分段错误,它说这是因为程序试图到达它没有权限的内存位置输入,但问题是当我从 Tab1 选择一个特殊元素时,例如 Tab1[5] 并将其传递给 Calc2 中的 factorielleRecursive 它工作得很好,有什么想法吗?
Program recursive;
Type
T = array [1..10] of LongInt;
Var
Tab1, Tab2 : T;
num : integer;
Function FactorielleIterative(N : integer) : integer;
Var
F, i : integer;
Begin
F := 1;
for i:=1 to N Do
F := F*i;
FactorielleIterative := F;
End;
Function FactorielleRecursive(N : LongInt) : LongInt;
Begin
if (N=1) Then
FactorielleRecursive := 1
Else
FactorielleRecursive := N * FactorielleRecursive(N-1);
End;
Procedure Fill(var Tab : T);
Var
i : Integer;
Begin
Randomize;
For i:=1 to 10 Do
Begin
Tab[i] := Random(10);
End;
For i:=1 to 10 Do
Write('[', Tab[i], '] ');
End;
Procedure Calc1(Tab1 : T; var Tab2 : T);
Var
i : integer;
Begin
For i:=1 to 10 Do
Begin
Tab2[i] := FactorielleIterative(Tab1[i]);
End;
For i:=1 to 10 Do
Write('[', Tab2[i], '] ');
End;
Procedure Calc2(Tab : T; var Tab2 : T);
Var
i : integer;
Begin
For i:=1 to 10 Do
Begin
Tab2[i] := FactorielleRecursive(Tab[i]);
End;
For i:=1 to 10 Do
Write('[', Tab2[i], '] ');
End;
Begin
Write('Tab1 : ');
Writeln;
Fill(Tab1);
Writeln;
Writeln;
Write('Tab2 : Iterative method');
Writeln;
Calc1(Tab1, Tab2);
Writeln;
Writeln;
Write('Tab2 : Recursive method');
Writeln;
Calc2(Tab1, Tab2);
Readln;
End.
我的想法:
- 我无法在我的设置中重现此问题:
bash$ fpc so.pas && ./so
Free Pascal Compiler version 3.2.0+dfsg-12 [2021/01/25] for x86_64
Copyright (c) 1993-2020 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling so.pas
so.pas(6,1) Note: Local variable "num" not used
Linking so
76 lines compiled, 0.1 sec
1 note(s) issued
注意:应删除未使用的变量。
您能否提供有关您的编译器及其编译时选项以及您的 OS 的更多详细信息?
Tab1[5]
只是一个随机值:它将 运行 更改为 运行。你是如何用它来验证的?你知道它现在的价值是多少吗?我从主块调用FactorielleRecursive(10);
并且我没有遇到任何问题。此问题在您的 运行 时间环境中是间歇性的吗?您的迭代函数只获取和 returns
Integer
。我认为您应该像递归方式那样将 return 类型更改为LongInt
。这里是两个版本之间的 运行 时间差(有一些溢出:见负值):
Tab2 : Iterative method
[5040]
[720]
[2]
[1]
[720]
[5040]
[24]
[1]
[-25216] <<<<<<<<<<<<<<<<< Integer overflow
[24]
Tab2 : Recursive method
[5040]
[720]
[2]
[1]
[720]
[5040]
[24]
[1]
[40320]
[24]
次要注意事项:
- 您可以将重复的代码部分提取到一个 procedure/function 中。在这种情况下,
for
循环重复 3 次以写出 Tab 数组的内容。 - 您可以将
Write
和WriteLn
合并为一个语句。例如WriteLn('Tab2 : Iterative method');
- 它是一种更紧凑的形式。
您没有考虑如果 Tab[]
数组包含零值会发生什么。这种情况是可能的,因为您调用 Random(10)
将 return 范围为 0 .. 9.
在 Function FactorielleIterative()
中,零参数被视为“1”值(因为 for
循环未执行)。
在 Function FactorielleRecursive()
中,零参数被视为“0”值,递归调用的结果 FactorielleRecursive(N-1);
导致范围溢出。
解决方法很简单,所以我把它留给你来解决,以免破坏你的作业。