목차
问题内容
解决方法
백엔드 개발 Golang 다른 스택을 사용할 때 SIGSEGV 또는 SIGTRAP과 함께 ucontext 충돌을 (의도적으로) 사용하는 Golang+CGO

다른 스택을 사용할 때 SIGSEGV 또는 SIGTRAP과 함께 ucontext 충돌을 (의도적으로) 사용하는 Golang+CGO

Feb 09, 2024 pm 12:15 PM
스택 오버플로

使用 ucontext 的 Golang+CGO 在使用不同堆栈时因 SIGSEGV 或 SIGTRAP 崩溃(故意)崩溃

php小编新一为您介绍一种使用ucontext的Golang+CGO技术,该技术在切换不同堆栈时可能会因为SIGSEGV或SIGTRAP而导致崩溃。这种崩溃是故意造成的,通过这种方式可以更好地理解和调试程序中的问题。本文将详细介绍如何利用ucontext和Golang+CGO技术进行堆栈切换,并对可能出现的崩溃进行分析和解决。无论您是初学者还是有一定经验的开发者,相信这篇文章都会对您有所帮助。

问题内容

我目前正在编写Golang + CGO程序,并将在CGO中使用posix ucontext。由于我所有的核心逻辑都将在ucontext的bind函数中,所以我们应该捕获所有错误的代码。我通过访问空指针来测试它,这给了我完全不同的行为,所有这些行为都取决于 ucontext 使用的堆栈位置。以下是带有简化示例的更多详细信息。

如果我在线程的堆栈上分配ucontext堆栈,它将触发SIGSEGV。但如果我在堆上分配它,它会首先触发 SIGSEGV,然后在调用 morestack_noctxt 时触发 SIGTRAP,然后再调用 runtime.sigpanic。我该如何解决这个问题或者如何获取 SIGSEGV?为什么需要morestack?

以下均为详细信息,任何建议或意见将不胜感激。谢谢!

崩溃(使用 malloc 堆栈):

<code>fatal: morestack on g0
SIGTRAP: trace trap
PC=0x45f342 m=0 sigcode=128
signal arrived during cgo execution

goroutine 1 [syscall]:
runtime.cgocall(0x464870, 0xc000067f60)
    /usr/local/go/src/runtime/cgocall.go:157 +0x5c fp=0xc000067f38 sp=0xc000067f00 pc=0x40465c
main._Cfunc_core_logic()
    _cgo_gotypes.go:39 +0x45 fp=0xc000067f60 sp=0xc000067f38 pc=0x4646e5
main.coreLogic()
    /container_share/works/badstack/main.go:46 +0x17 fp=0xc000067f70 sp=0xc000067f60 pc=0x464737
main.main()
    /container_share/works/badstack/main.go:51 +0x17 fp=0xc000067f80 sp=0xc000067f70 pc=0x464777
runtime.main()
    /usr/local/go/src/runtime/proc.go:250 +0x1d3 fp=0xc000067fe0 sp=0xc000067f80 pc=0x436913
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000067fe8 sp=0xc000067fe0 pc=0x45f4a1

goroutine 2 [force gc (idle)]:
runtime.gopark(0x47a860, 0x6cb4d0, 0x11, 0x14, 0x1)
    /usr/local/go/src/runtime/proc.go:381 +0xfd fp=0xc000054f88 sp=0xc000054f58 pc=0x436dbd
runtime.goparkunlock(0x0?, 0x0?, 0x0?, 0x0?)
    /usr/local/go/src/runtime/proc.go:387 +0x2a fp=0xc000054fb8 sp=0xc000054f88 pc=0x436e4a
runtime.forcegchelper()
    /usr/local/go/src/runtime/proc.go:305 +0xb0 fp=0xc000054fe0 sp=0xc000054fb8 pc=0x436b90
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000054fe8 sp=0xc000054fe0 pc=0x45f4a1
created by runtime.init.6
    /usr/local/go/src/runtime/proc.go:293 +0x25

goroutine 3 [GC sweep wait]:
runtime.gopark(0x47a860, 0x6cb640, 0xc, 0x14, 0x1)
    /usr/local/go/src/runtime/proc.go:381 +0xfd fp=0xc000055758 sp=0xc000055728 pc=0x436dbd
runtime.goparkunlock(0x0?, 0x0?, 0x0?, 0x0?)
    /usr/local/go/src/runtime/proc.go:387 +0x2a fp=0xc000055788 sp=0xc000055758 pc=0x436e4a
runtime.bgsweep(0x0?)
    /usr/local/go/src/runtime/mgcsweep.go:278 +0x98 fp=0xc0000557c8 sp=0xc000055788 pc=0x421998
runtime.gcenable.func1()
    /usr/local/go/src/runtime/mgc.go:178 +0x26 fp=0xc0000557e0 sp=0xc0000557c8 pc=0x415f66
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc0000557e8 sp=0xc0000557e0 pc=0x45f4a1
created by runtime.gcenable
    /usr/local/go/src/runtime/mgc.go:178 +0x6b

goroutine 4 [GC scavenge wait]:
runtime.gopark(0x47a860, 0x6cb6c0, 0xd, 0x14, 0x2)
    /usr/local/go/src/runtime/proc.go:381 +0xfd fp=0xc000055f48 sp=0xc000055f18 pc=0x436dbd
runtime.goparkunlock(0x47ca80?, 0x1?, 0x0?, 0x0?)
    /usr/local/go/src/runtime/proc.go:387 +0x2a fp=0xc000055f78 sp=0xc000055f48 pc=0x436e4a
runtime.(*scavengerState).park(0x6cb6c0)
    /usr/local/go/src/runtime/mgcscavenge.go:400 +0x4b fp=0xc000055fa0 sp=0xc000055f78 pc=0x41f44b
runtime.bgscavenge(0x0?)
    /usr/local/go/src/runtime/mgcscavenge.go:628 +0x45 fp=0xc000055fc8 sp=0xc000055fa0 pc=0x41fa25
runtime.gcenable.func2()
    /usr/local/go/src/runtime/mgc.go:179 +0x26 fp=0xc000055fe0 sp=0xc000055fc8 pc=0x415f06
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000055fe8 sp=0xc000055fe0 pc=0x45f4a1
created by runtime.gcenable
    /usr/local/go/src/runtime/mgc.go:179 +0xaa

rax    0x17
rbx    0x476413
rcx    0x460c95
rdx    0x17
rdi    0x2
rsi    0x476413
rbp    0x7f18906b3ff0
rsp    0x7f18906b3fd8
r8     0xffffffff
r9     0x0
r10    0x8
r11    0x246
r12    0xc000067c70
r13    0x0
r14    0x6cb760
r15    0x0
rip    0x45f342
rflags 0x206
cs     0x33
fs     0x0
gs     0x0
</code>
로그인 후 복사

崩溃(线程堆栈):

<code>fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4647a0]

runtime stack:
runtime.throw({0x479118?, 0xffffffffffffffff?})
    /usr/local/go/src/runtime/panic.go:1047 +0x5d fp=0x7fff293551f0 sp=0x7fff293551c0 pc=0x43417d
runtime.sigpanic()
    /usr/local/go/src/runtime/signal_unix.go:825 +0x285 fp=0x7fff29355220 sp=0x7fff293551f0 pc=0x4495a5

goroutine 1 [syscall]:
runtime.cgocall(0x464890, 0xc000067f60)
    /usr/local/go/src/runtime/cgocall.go:157 +0x5c fp=0xc000067f38 sp=0xc000067f00 pc=0x40465c
main._Cfunc_core_logic()
    _cgo_gotypes.go:39 +0x45 fp=0xc000067f60 sp=0xc000067f38 pc=0x4646e5
main.coreLogic()
    /container_share/works/badstack/main.go:46 +0x17 fp=0xc000067f70 sp=0xc000067f60 pc=0x464737
main.main()
    /container_share/works/badstack/main.go:51 +0x17 fp=0xc000067f80 sp=0xc000067f70 pc=0x464777
runtime.main()
    /usr/local/go/src/runtime/proc.go:250 +0x1d3 fp=0xc000067fe0 sp=0xc000067f80 pc=0x436913
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000067fe8 sp=0xc000067fe0 pc=0x45f4a1

goroutine 2 [force gc (idle)]:
runtime.gopark(0x47a880, 0x6cb4d0, 0x11, 0x14, 0x1)
    /usr/local/go/src/runtime/proc.go:381 +0xfd fp=0xc000054f88 sp=0xc000054f58 pc=0x436dbd
runtime.goparkunlock(0x0?, 0x0?, 0x0?, 0x0?)
    /usr/local/go/src/runtime/proc.go:387 +0x2a fp=0xc000054fb8 sp=0xc000054f88 pc=0x436e4a
runtime.forcegchelper()
    /usr/local/go/src/runtime/proc.go:305 +0xb0 fp=0xc000054fe0 sp=0xc000054fb8 pc=0x436b90
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000054fe8 sp=0xc000054fe0 pc=0x45f4a1
created by runtime.init.6
    /usr/local/go/src/runtime/proc.go:293 +0x25

goroutine 3 [GC sweep wait]:
runtime.gopark(0x47a880, 0x6cb640, 0xc, 0x14, 0x1)
    /usr/local/go/src/runtime/proc.go:381 +0xfd fp=0xc000055758 sp=0xc000055728 pc=0x436dbd
runtime.goparkunlock(0x0?, 0x0?, 0x0?, 0x0?)
    /usr/local/go/src/runtime/proc.go:387 +0x2a fp=0xc000055788 sp=0xc000055758 pc=0x436e4a
runtime.bgsweep(0x0?)
    /usr/local/go/src/runtime/mgcsweep.go:278 +0x98 fp=0xc0000557c8 sp=0xc000055788 pc=0x421998
runtime.gcenable.func1()
    /usr/local/go/src/runtime/mgc.go:178 +0x26 fp=0xc0000557e0 sp=0xc0000557c8 pc=0x415f66
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc0000557e8 sp=0xc0000557e0 pc=0x45f4a1
created by runtime.gcenable
    /usr/local/go/src/runtime/mgc.go:178 +0x6b

goroutine 4 [GC scavenge wait]:
runtime.gopark(0x47a880, 0x6cb6c0, 0xd, 0x14, 0x2)
    /usr/local/go/src/runtime/proc.go:381 +0xfd fp=0xc000055f48 sp=0xc000055f18 pc=0x436dbd
runtime.goparkunlock(0x47caa0?, 0x1?, 0x0?, 0x0?)
    /usr/local/go/src/runtime/proc.go:387 +0x2a fp=0xc000055f78 sp=0xc000055f48 pc=0x436e4a
runtime.(*scavengerState).park(0x6cb6c0)
    /usr/local/go/src/runtime/mgcscavenge.go:400 +0x4b fp=0xc000055fa0 sp=0xc000055f78 pc=0x41f44b
runtime.bgscavenge(0x0?)
    /usr/local/go/src/runtime/mgcscavenge.go:628 +0x45 fp=0xc000055fc8 sp=0xc000055fa0 pc=0x41fa25
runtime.gcenable.func2()
    /usr/local/go/src/runtime/mgc.go:179 +0x26 fp=0xc000055fe0 sp=0xc000055fc8 pc=0x415f06
runtime.goexit()
    /usr/local/go/src/runtime/asm_amd64.s:1598 +0x1 fp=0xc000055fe8 sp=0xc000055fe0 pc=0x45f4a1
created by runtime.gcenable
    /usr/local/go/src/runtime/mgc.go:179 +0xaa
</code>
로그인 후 복사

GDB(带 malloc 堆栈):

这将调用runtime.morestack_noctxt,并最终得到badstack,因为它位于g0的堆栈上。

<code>(gdb) b runtime.sigpanic
Breakpoint 1 at 0x449320: file /usr/local/go/src/runtime/signal_unix.go, line 822.
(gdb) r
Starting program: /container_share/works/badstack/main
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7fffd05d3700 (LWP 213229)]
[New Thread 0x7fffcfdd2700 (LWP 213230)]
[New Thread 0x7fffcf5d1700 (LWP 213231)]
[New Thread 0x7fffcedd0700 (LWP 213232)]
[New Thread 0x7fffce58f700 (LWP 213233)]
[New Thread 0x7fffcdd8e700 (LWP 213234)]

Thread 1 "main" received signal SIGSEGV, Segmentation fault.
0x00000000004647a0 in core () at /container_share/works/badstack/main.go:18
18    *ptr = 1024;
(gdb) c
Continuing.

Thread 1 "main" hit Breakpoint 1, runtime.sigpanic () at /usr/local/go/src/runtime/signal_unix.go:822
822 func sigpanic() {
(gdb) p $rsp
$1 = (void *) 0x7fffcd58cfe8
(gdb) x/x $r14+0x10
0x6cb770 <runtime.g0+16>:   0xff7fed70
(gdb) c
Continuing.
fatal: morestack on g0
</code>
로그인 후 복사

GDB(带有线程堆栈):

这似乎一切都按预期进行。

<code>(gdb) b runtime.sigpanic
Breakpoint 1 at 0x449320: file /usr/local/go/src/runtime/signal_unix.go, line 822.
(gdb) r
Starting program: /container_share/works/badstack/main
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7fffd05d3700 (LWP 214288)]
[New Thread 0x7fffcfdd2700 (LWP 214289)]
[New Thread 0x7fffcf5d1700 (LWP 214290)]
[New Thread 0x7fffcedd0700 (LWP 214291)]
[New Thread 0x7fffce5cf700 (LWP 214292)]

Thread 1 "main" received signal SIGSEGV, Segmentation fault.
0x00000000004647a0 in core () at /container_share/works/badstack/main.go:18
18    *ptr = 1024;
(gdb) c
Continuing.

Thread 1 "main" hit Breakpoint 1, runtime.sigpanic () at /usr/local/go/src/runtime/signal_unix.go:822
822 func sigpanic() {
(gdb) p $rsp
$1 = (void *) 0x7fffffffd8e8
(gdb) x/x $r14+0x10
0x6cb770 <runtime.g0+16>:   0xff7fed70
(gdb) c
Continuing.
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4647a0]
</code>
로그인 후 복사

环境:

❯ clang -v                                                                     
clang version 16.0.6 (Red Hat 16.0.6-2.module_el8+588+6f71ce7b)

❯ gcc -v                                                                       
gcc version 8.4.1 20200928 (Red Hat 8.4.1-1) (GCC)

❯ uname -a
Linux 6cc94b77abd7 6.4.16-orbstack-00103-g02b40eb69695 #1 SMP Wed Sep 13 10:13:30 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
로그인 후 복사

复制者:

编译: CC=clang CXX=clang++ CFLAGS="-g -O0" go build -gcflags="all=-N -l" main.go

package main

/*
#include <stdio.h>
#include <stddef.h>
#include <ucontext.h>
#include <stdlib.h>

static ucontext_t uctx_main, uctx_core;

void core()
{
  // core logic


  // trigger crash
  int* ptr = NULL;
  *ptr = 1024;
}

void core_logic()
{
  size_t size = 1024 * 1024;
  char stack[size]; // SIGSEGV
  //void* stack = malloc(size); // SIGTRAP

  if (getcontext(&uctx_core) == -1)
    printf("failed to getcontext");

  uctx_core.uc_stack.ss_sp = stack;
  uctx_core.uc_stack.ss_size = size;
  uctx_core.uc_link = &uctx_main;

  makecontext(&uctx_core, core, 0);

  if (swapcontext(&uctx_main, &uctx_core) == -1)
    printf("failed to swapcontext");

  printf("back\n");
}
*/
// #cgo CFLAGS: -g -O0
import "C"

func coreLogic() {
  C.core_logic()
}

func main() {
  // Call the C function from Go
  coreLogic()
}
로그인 후 복사

这是我的猜测,但似乎不正确:当我使用堆堆栈时,它被视为有堆栈溢出,并且应该更多堆栈,但最终发现它是g0,然后是致命的。但看起来 goroutine 的堆栈比线程的堆栈低得多?

更新于2023年9月24日:

对于纯 C 程序,无论我使用什么堆栈,它都会获得 SIGSEGV。

<code>#include <stdio.h>
#include <stddef.h>
#include <ucontext.h>
#include <stdlib.h>

static ucontext_t uctx_main, uctx_core;

void core()
{
  // core logic


  // trigger crash
  int* ptr = NULL;
  *ptr = 1024;
}

void core_logic()
{
  size_t size = 100 * 1024 * 1024;
  //char stack[size]; // SIGSEGV
  void* stack = malloc(size); // SIGTRAP

  if (getcontext(&uctx_core) == -1)
    printf("failed to getcontext");

  uctx_core.uc_stack.ss_sp = stack;
  uctx_core.uc_stack.ss_size = size;
  uctx_core.uc_link = &uctx_main;

  makecontext(&uctx_core, core, 0);

  if (swapcontext(&uctx_main, &uctx_core) == -1)
    printf("failed to swapcontext");

  printf("back\n");
}

void coreLogic() {
  core_logic();
}

int main() {
  coreLogic();
  return 0;
}
</code>
로그인 후 복사

解决方法

最后,我在 Go 团队成员的帮助下解决了这个问题,打开了一个问题 在 Golang 的 github 存储库中,如果您需要的话。

TL;DR:这是从 Go1.21 开始的错误,应该在 Go1.22 中修复。即使您使用 Go1.20,由于另一个错误,您可能仍然面临这个问题。如果有人需要的话,也许我稍后会发布更多详细信息,或者您可以在我之前提到的问题中查看更多详细信息。

위 내용은 다른 스택을 사용할 때 SIGSEGV 또는 SIGTRAP과 함께 ucontext 충돌을 (의도적으로) 사용하는 Golang+CGO의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Spring Security 6: cors()는 더 이상 사용되지 않으며 제거 대상으로 표시됩니다. Spring Security 6: cors()는 더 이상 사용되지 않으며 제거 대상으로 표시됩니다. Feb 10, 2024 pm 11:45 PM

나는 아래에 있는 혁신적인 대안: publicSecurityFilterChainsecurityFilterChain(HttpSecurityhttp)throwsException{returnhttp.httpBasic().disable().cors().and().csrf().disable().authorizeHttpRequests().requestMatchers("

C++ 람다 표현식은 재귀를 지원합니까? C++ 람다 표현식은 재귀를 지원합니까? Apr 17, 2024 pm 09:06 PM

예, C++ Lambda 표현식은 std::function을 사용하여 재귀를 지원할 수 있습니다. std::function을 사용하여 Lambda 표현식에 대한 참조를 캡처합니다. 캡처된 참조를 사용하면 Lambda 표현식이 자신을 재귀적으로 호출할 수 있습니다.

다른 스택을 사용할 때 SIGSEGV 또는 SIGTRAP과 함께 ucontext 충돌을 (의도적으로) 사용하는 Golang+CGO 다른 스택을 사용할 때 SIGSEGV 또는 SIGTRAP과 함께 ucontext 충돌을 (의도적으로) 사용하는 Golang+CGO Feb 09, 2024 pm 12:15 PM

저는 현재 Golang+CGO 프로그램을 작성 중이며 CGO에서 posixucontext를 사용할 예정입니다. 모든 핵심 로직은 ucontext의 바인드 기능에 있으므로 코드의 모든 오류를 잡아야 합니다. 나는 ucontext에서 사용하는 스택 위치에 따라 완전히 다른 동작을 제공하는 널 포인터에 액세스하여 이를 테스트했습니다. 다음은 단순화된 예를 통해 더 자세한 내용입니다. 스레드 스택에 ucontext 스택을 할당하면 SIGSEGV가 트리거됩니다. 하지만 힙에 할당하면 먼저 SIGSEGV가 트리거되고 morestack_noctxt가 호출될 때 SIGT가 트리거됩니다.

C++가 실행을 시작할 때 충돌이 발생하는 이유는 무엇입니까? C++가 실행을 시작할 때 충돌이 발생하는 이유는 무엇입니까? Apr 22, 2024 pm 05:57 PM

시작할 때 C++ 프로그램이 충돌하는 이유는 다음과 같습니다: 필수 라이브러리 또는 종속성 누락, 초기화되지 않은 포인터 또는 참조 스택 오버플로, 세그폴트, 운영 체제 구성 문제, 프로그램 오류, 하드웨어 문제

C++ 런타임 오류: '스택 오버플로'를 해결하는 방법은 무엇입니까? C++ 런타임 오류: '스택 오버플로'를 해결하는 방법은 무엇입니까? Aug 25, 2023 pm 10:00 PM

C++ 런타임 오류 해결 방법: '스택오버플로우' C++ 프로그램에서 재귀 수준이 너무 높거나 프로그램에서 사용하는 메모리가 스택 용량을 초과하면 런타임 오류 '스택오버플로우'가 발생합니다. 이 오류가 발생하면 프로그램이 충돌하여 구체적인 원인을 파악하기 어렵습니다. 이 문서에서는 '스택오버플로' 오류를 해결하는 몇 가지 방법을 소개하고 몇 가지 코드 예제를 제공합니다. 런타임 오류 "stackoverflow"의 주요 원인은 스택 내에서 발생합니다.

C++ 함수의 재귀적 구현: 재귀적 알고리즘과 비재귀적 알고리즘의 비교 분석? C++ 함수의 재귀적 구현: 재귀적 알고리즘과 비재귀적 알고리즘의 비교 분석? Apr 22, 2024 pm 03:18 PM

재귀 알고리즘은 함수 자체 호출을 통해 구조화된 문제를 해결하지만 간단하고 이해하기 쉽다는 장점이 있지만 효율성이 떨어지고 스택 오버플로가 발생할 수 있다는 단점이 있습니다. 스택 데이터 구조의 장점은 더 효율적이고 스택 오버플로를 방지한다는 것입니다. 단점은 코드가 더 복잡할 수 있다는 것입니다. 재귀적 또는 비재귀적 선택은 문제와 구현의 특정 제약 조건에 따라 달라집니다.

Java 함수와 Haskell 함수의 차이점은 무엇입니까? Java 함수와 Haskell 함수의 차이점은 무엇입니까? Apr 23, 2024 pm 09:18 PM

Java와 Haskell 함수의 주요 차이점은 다음과 같습니다. 구문: Java는 return 키워드를 사용하여 결과를 반환하는 반면 Haskell은 할당 기호(=)를 사용합니다. 실행 모델: Java는 순차 실행을 사용하는 반면 Haskell은 지연 평가를 사용합니다. 유형 시스템: Java에는 정적 유형 시스템이 있는 반면 Haskell에는 컴파일 시간과 런타임에 유형을 확인하는 강력하고 유연한 유형 시스템이 있습니다. 실용적인 성능: Haskell은 꼬리 재귀를 사용하는 반면, Java는 재귀를 사용하므로 대규모 입력을 처리할 때 Java보다 더 효율적입니다.

C++ 함수 재귀 설명: 재귀의 대안 C++ 함수 재귀 설명: 재귀의 대안 May 01, 2024 pm 04:54 PM

재귀는 함수가 자신을 호출하는 기술이지만 스택 오버플로와 비효율성의 단점이 있습니다. 대안으로는 컴파일러가 재귀 호출을 루프로 최적화하는 반복, 재귀 대신 루프와 코루틴을 사용하여 재귀 동작을 시뮬레이션하는 반복이 있습니다.

See all articles