将数组元素传递给 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 数组的内容。
  • 您可以将 WriteWriteLn 合并为一个语句。例如 WriteLn('Tab2 : Iterative method'); - 它是一种更紧凑的形式。

您没有考虑如果 Tab[] 数组包含零值会发生什么。这种情况是可能的,因为您调用 Random(10) 将 return 范围为 0 .. 9.

的值

Function FactorielleIterative() 中,零参数被视为“1”值(因为 for 循环未执行)。

Function FactorielleRecursive() 中,零参数被视为“0”值,递归调用的结果 FactorielleRecursive(N-1); 导致范围溢出。

解决方法很简单,所以我把它留给你来解决,以免破坏你的作业。