ネタ元
PowerShellで似たようなことをやってみたくなったので、やってみた。
バージョン
PowerShellでスタックオーバーフローを起こしたいなら黙ってv2を使うんだ。
PS C:\> $PSVersionTable.PSVersion.ToString()
2.0
スタックオーバフローが起きる関数
filter countDown ($num)
{
if ($num -eq 1) {return 1}
if ($num % 200 -eq 0) {Write-Host $num}
countDown ($num - 1)
}
PS C:\> countDown 1000
1000
800
600
400
200
呼び出しの深さのオーバーフローのため、スクリプトが失敗しました。呼び出しの深さが 1001 に達しましたが、最大値は 1000 です。
+ CategoryInfo : InvalidOperation: (1001:Int32) []、ParentContainsErrorRecordException
+ FullyQualifiedErrorId : CallDepthOverflow
評価が遅延されるように、関数を定義し直す。
filter countDown2 ($num)
{
if ($num -eq 1) {return 1}
if ($num % 200 -eq 0) {Write-Host $num}
New-Trampoline $function:countDown2 ($num - 1)
}
filter New-Trampoline
([ScriptBlock] $ScriptBlock, [Object[]]$ArgumentList)
{$ScriptBlock | Add-Member NoteProperty ArgumentList $ArgumentList -PassThru}
トランポリン
filter Invoke-Trampoline
{
while ($_ -is [ScriptBlock] -and ($_ | Get-Member ArgumentList))
{$_ = Invoke-Command $_ -ArgumentList $_.ArgumentList}
$_
}
確かにスタックオーバーフローは起こらなくなる
PS C:\> countDown2 1000 | Invoke-Trampoline
1000
800
600
400
200
1
おもしろ~い