“goto”진술로 어떤 종류의 버그가 발생합니까? 역사적으로 중요한 예가 있습니까?


103

루프에 중첩 된 루프를 없애기 위해 저장한다는 것을 이해합니다. 이 goto문장은 사용되지 않는 버그가 발생하기 쉬운 프로그래밍 스타일로 회피되고 비난됩니다.

XKCD 대체 텍스트 : "Neal Stephenson은 자신의 레이블 이름을 'dengo'라고 생각하는 것이 귀엽다고 생각합니다 . "
: http://xkcd.com/292/

내가 이것을 일찍 배웠기 때문에; goto실제로 어떤 유형의 버그가 실제로 발생하는지에 대한 통찰력이나 경험이 없습니다 . 그래서 우리는 여기서 무엇을 이야기하고 있습니까?

  • 불안정?
  • 유지할 수 없거나 읽을 수없는 코드?
  • 보안 취약점?
  • 완전히 다른 것?

"goto"문장은 실제로 어떤 종류의 버그를 유발합니까? 역사적으로 중요한 예가 있습니까?


33
이 주제에 관한 Dijkstra의 짧은 논문을 읽었습니까? (그것은 예 / 아니오 질문이며, 명백한 순간 "예"이외의 대답은 "아니오"입니다.)
John R. Strohm

2
나는 치명적인 오류가 발생했을 때 알람 종료가 있다고 가정합니다. 다시는 돌아 오지 않을 곳. 정전과 같이 장치 나 파일이 사라지는 것처럼. "on error goto"의 어떤 종류 ...하지만 요즘 "try-catch"구문으로 대부분의 "catastropic"오류를 처리 할 수 ​​있다고 생각합니다.
Lenne

13
아직 계산 된 GOTO를 언급 한 사람은 없습니다. 지구가 어렸을 때 BASIC은 줄 번호를 가지고있었습니다. 다음과 같이 쓸 수 있습니다 : 100 N = A * 100; GOTO N. 디버깅을 시도해보십시오 :)
mcottle

7
@ JohnR.Strohm Dijkstra의 논문을 읽었습니다. 1968 년에 작성되었으며 스위치 설명 및 기능과 같은 고급 기능을 포함하는 언어에서는 고 토스의 필요성이 줄어들 수 있다고 제안합니다. 그것은 goto가 흐름 제어의 주요 방법 인 언어에 대한 응답으로 작성되었으며 프로그램의 어느 지점 으로든 이동할 수 있습니다. 이 백서가 작성된 후 개발 된 언어 (예 : C)에서 goto는 동일한 스택 프레임의 위치로만 이동할 수 있으며 일반적으로 다른 옵션이 제대로 작동하지 않을 때만 사용됩니다. (계속 ...)
Ray

10
(... 계속) 그의 요점은 당시에는 유효했지만 goto가 좋은 아이디어인지 아닌지에 관계없이 더 이상 관련 이 없습니다. 우리가 어떤 식 으로든 다른 방식으로 논쟁하기를 원한다면 현대 언어와 관련된 논쟁이 이루어져야합니다. 그런데 Knuth의 "goto 문으로 구조화 된 프로그래밍" 읽었습니까?
Ray

답변:


2

다른 답변에서 아직 보지 못한 것을 볼 수있는 방법이 있습니다.

범위에 관한 것입니다. 좋은 프로그래밍 실습의 주요 기둥 중 하나는 스코프를 엄격하게 유지하는 것입니다. 단지 몇 가지 논리적 단계 이상을 감독하고 이해하는 정신적 능력이 부족하기 때문에 범위가 좁습니다. 따라서 작은 블록 (각각 하나가 "일"이 됨)을 만든 다음 하나가되는 더 큰 블록을 만드는 블록을 만듭니다. 이것은 일을 관리하고 이해하기 쉽게합니다.

goto는 논리의 범위를 전체 프로그램으로 효과적으로 확장시킵니다. 이것은 단지 몇 줄에 걸친 가장 작은 프로그램을 제외하고는 당신의 두뇌를 물리 칠 것입니다.

그래서 당신은 당신이 불쌍한 작은 머리를 조사하고 점검하기에 너무 많은 것이 있기 때문에 더 이상 실수를했는지 알 수 없습니다. 이것은 실제 문제이며 버그는 단지 결과 일뿐입니다.


로컬이 아닌 goto?
중복 제거기

thebrain.mcgill.ca/flash/capsules/experience_jaune03.html << 인간의 마음은 한 번에 평균 7 가지를 추적 할 수 있습니다. 범위를 확장하면 추적해야 할 더 많은 것들이 추가되므로 이론적 근거는이 한계에 부딪칩니다. 따라서 소개 될 버그의 유형은 누락과 건망증 일 가능성이 높습니다. 또한 "범위를 엄격하게 유지"하는 완화 전략과 모범 사례를 제공합니다. 따라서이 답변에 동의합니다. 잘 했어 마틴
Akiva

1
얼마나 멋진가요?! 200 개가 넘는 투표 중에서 1 개만 획득했습니다!
Martin Maat

68

goto그 자체가 나쁘지 는 않습니다 . 결국 컴퓨터의 모든 점프 명령은 고토 (goto)입니다. 문제는 "프로그래밍 된 프로그래밍 (flow-chart)"프로그래밍이라고 할 수있는 구조화 된 프로그래밍보다 인간적인 프로그래밍 스타일이 있다는 것입니다.

플로우 차트 프로그래밍 (내 세대 사람들이 배우고 아폴로 달 프로그램에 사용)에서, 문장 실행을위한 블록과 의사 결정을위한 다이아몬드가있는 다이어그램을 만들고, 그 라인을 모든 곳의 라인으로 연결할 수 있습니다. (소위 "스파게티 코드")

스파게티 코드의 문제점은 프로그래머가 자신이 옳은 것을 "알 수"있지만 어떻게 자신이나 다른 사람에게 그것을 증명할 수 있는가하는 것입니다. 실제로, 잠재적 인 오작동이있을 수 있으며 항상 정확하다는 지식은 틀릴 수 있습니다.

함께 온 구조화 프로그래밍 을 시작 엔드 블록을위한 반면, IF-다른, 등등. 이것들은 여전히 ​​어떤 일을 할 수 있다는 이점이 있었지만, 조심스럽게 조심한다면 코드가 올바른지 확인할 수 있습니다.

물론 사람들은 없이도 스파게티 코드를 작성할 수 있습니다 goto. 일반적인 방법은 while(...) switch( iState ){...다른 경우 iState를 다른 값으로 설정하는를 작성하는 것 입니다. 실제로 C 또는 C ++에서는 매크로를 작성하여 이름을 GOTO지정할 수 있으므로 사용하지 않는다고 말하는 goto것은 차이가없는 구별입니다.

코드 검증이 무제한을 배제 할 수있는 방법의 예로써 goto, 오래 전에 나는 동적으로 변화하는 사용자 인터페이스에 유용한 제어 구조를 우연히 발견했다. 나는 그것을 차등 실행 이라고 불렀다 . 그것은 완전히 튜링 보편적이지만, 그 정확성 증거는 순수한 구조적 프로그래밍에 따라 달라집니다 - 아니 goto, return, continue, break, 또는 예외.

여기에 이미지 설명을 입력하십시오


49
구조화 된 프로그래밍을 사용하여 작성하더라도 가장 간단한 프로그램을 제외하고는 정확성을 입증 할 수 없습니다 . 신뢰 수준 만 높일 수 있습니다. 구조화 된 프로그래밍이이를 수행합니다.
Robert Harvey

23
@MikeDunlavey : 관련 : "위의 코드에서 버그에주의하십시오. 시도한 것이 아니라 올바른 것으로 판명되었습니다." staff.fnwi.uva.nl/p.vanemdeboas/knuthnote.pdf
Mooing Duck

26
@RobertHarvey 정확성 증명이 사소한 프로그램에만 실용적이라는 것은 사실 이 아닙니다. 그러나 구조화 된 프로그래밍보다 더 전문화 된 도구가 필요합니다.
Mike Haskel

18
@MSalters : 연구 프로젝트입니다. 이러한 연구 프로젝트의 목표 는 리소스가있는 경우 검증 된 컴파일러를 작성할 있음을 보여주는 것입니다 . 현재 작업을 살펴보면, 이후 버전의 C를 지원하는 데 관심이없고 증명할 수있는 정확성 속성을 확장하는 데 관심이 있음을 알 수 있습니다. 그리고이를 위해 C90, C99, C11, Pascal, Fortran, Algol 또는 Plankalkül을 지원하는지 여부는 전혀 관련이 없습니다.
Jörg W Mittag

8
@martineau : 나는 "보손 프레이즈"의 리리이다. 프로그래머들은 그렇지 않다면 앉을 수 있기 때문에 나쁘거나 좋다는 것에 동의한다. 사물에 대한 더 기본적인 이유가 있어야합니다.
Mike Dunlavey 2016 년

63

왜 고토가 위험한가요?

  • goto자체적으로 불안정성을 유발하지 않습니다. 약 10 만 goto 에도 Linux 커널 은 여전히 ​​안정성 모델입니다.
  • goto그 자체만으로는 보안 취약점이 발생하지 않아야합니다. 그러나 일부 언어에서는 예외 관리 블록 과 함께 try/ catch예외 관리 블록을 혼합하면 이 CERT 권장 사항에 설명 된대로 취약점이 발생할 수 있습니다 . 주류 C ++ 컴파일러는 이러한 오류를 표시하고 방지하지만 불행히도 이전 또는 더 이국적인 컴파일러는 그렇지 않습니다.
  • goto읽을 수없고 유지할 수없는 코드를 발생시킵니다. 이것은 스파게티 코드 라고도 합니다 . 왜냐하면 스파게티 플레이트 에서처럼 너무 많은 고토가있을 때 제어 흐름을 따르는 것이 매우 어렵 기 때문입니다.

스파게티 코드를 피하고 고토를 몇 개만 사용하더라도 버그와 리소스 누출을 여전히 촉진합니다.

  • 명확한 중첩 블록과 루프 또는 스위치와 함께 구조 프로그래밍을 사용하는 코드는 따르기 쉽습니다. 제어 흐름은 매우 예측 가능합니다. 따라서 불변량을 존중하는 것이 더 쉽습니다.
  • A의 goto문, 당신은 간단 흐름을 중단하고 기대를 휴식. 예를 들어, 여전히 자원을 비워야한다는 것을 알지 못할 수 있습니다.
  • goto다른 장소의 많은 사람들 이 단일 goto 대상으로 보낼 수 있습니다. 따라서이 장소에 도달했을 때의 상태를 확실하게 알 수 없습니다. 그러므로 틀리거나 근거가없는 가정을 할 위험은 상당히 크다.

추가 정보 및 인용문 :

C는 무한히 어설픈 goto문장과 레이블을 제공합니다 . 공식적으로 goto는 결코 필요하지 않으며 실제로는 코드없이 코드를 작성하는 것이 거의 항상 쉽습니다. (...)
그럼에도 불구하고 우리는 고토의이 장소를 찾을 수있는 몇 가지 상황을 제안합니다. 가장 일반적인 용도는 한 번에 두 개의 루프를 끊는 것과 같이 일부 중첩 된 구조에서 처리를 포기하는 것입니다. (...)
우리는 그 문제에 대해 독단적이지는 않지만, goto 선언문을 조금만 사용해야 하는 것 같습니다 .

  • James Gosling & Henry McGilton은 1995 년 자바 환경 백서 에서 다음과 같이 썼습니다 .

    더 이상 Goto 문
    이 없습니다. Java에는 goto 문이 없습니다. 연구 결과에 따르면 goto는 단순히 "있어서"있기보다는 자주 사용됩니다. goto를 제거하면 언어가 간단 해졌습니다 (...) C 코드의 약 100,000 줄에 대한 연구에 따르면 goto 문의 대략 90 %가 순전히 중첩 루프에서 벗어나는 효과를 얻는 데 사용 된 것으로 나타났습니다. 위에서 언급했듯이, 다단계 나누기와 계속해서 goto 문의 필요성을 대부분 제거합니다.

  • Bjarne Stroustrup 은 다음과 같은 매력적인 용어로 용어집 에서 goto를 정의합니다 .

    goto-악명 높은 goto. 기계 생성 C ++ 코드에 주로 유용합니다.

언제 갈 수 있나요?

K & R처럼 저는 고 토스에 대해 독단적이지 않습니다. 나는 goto가 인생을 편하게 할 수있는 상황이 있음을 인정한다.

일반적으로 C에서 goto는 다중 레벨 루프 종료 또는 지금까지 할당 된 모든 자원을 해제 / 해제하는 적절한 종료점에 도달해야하는 오류 처리를 허용합니다 (예 : 순서대로 다중 할당은 다중 레이블을 의미 함). 이 기사 는 Linux 커널에서 goto의 다른 용도를 정량화합니다.

개인적으로 나는 그것을 피하고 10 년 동안 최대 10 개의 고토를 사용했습니다. 나는 if더 읽기 쉽다고 생각하는 중첩 된을 사용하는 것을 선호합니다 . 이것이 너무 깊은 중첩으로 이어질 때 함수를 작은 부분으로 분해하거나 부울 표시기를 계단식으로 사용하도록 선택했습니다. 오늘날의 최적화 컴파일러는와 동일한 코드와 거의 동일한 코드를 생성 할만큼 영리 goto합니다.

goto의 사용은 언어에 따라 크게 다릅니다.

  • C ++에서 RAII를 올바르게 사용 하면 컴파일러가 범위를 벗어난 객체를 자동으로 파괴하므로 리소스 / 잠금이 정리되어 더 이상 갈 필요가 없습니다.

  • 자바에서는 더 고토의 필요성 (자바의 위 저자의 인용이 볼 수 없다 우수한 스택 오버플로 대답 ) : 엉망이, 청소 가비지 컬렉터 break, continuetry/ catch예외 처리는 모든 케이스 커버 goto도움이 될 수있는, 그러나으로는 더 안전하고 더 나은 방법. Java의 인기는 현대 언어로 goto 문을 피할 수 있음을 증명합니다.

유명한 SSL goto fail 취약점 확대

중요 면책 조항 : 의견의 격렬한 논의를 고려할 때 goto 문 이이 버그의 유일한 원인이라고 주장하지 않는다는 것을 분명히하고 싶습니다. 나는 goto가 없으면 버그가 없다고 가정하지 않습니다. 고토가 심각한 버그에 관여 할 수 있음을 보여주고 싶습니다.

나는 goto프로그래밍의 역사에서 몇 가지 심각한 버그가 관련되어 있는지 잘 모른다 . 그러나 iOS의 보안을 약화시킨 유명한 Apple SSL 버그 가있었습니다. 이 버그를 일으킨 goto진술 은 잘못된 진술이었습니다.

어떤 사람들은 버그의 근본 원인 자체가 goto 문이 아니라 잘못된 복사 / 붙여 넣기, 잘못된 들여 쓰기, 조건부 블록 주위에 중괄호 누락 또는 개발자의 작업 습관이라고 주장합니다. 나는 그것들 중 어느 것도 확인할 수 없다.이 모든 주장들은 가능한 가설과 해석 일 것이다. 아무도 모른다. ( 한편, 누군가가 의견에서 제안한대로 잘못 된 합병의 가설은 동일한 기능의 다른 들여 쓰기 불일치를 고려할 때 매우 좋은 후보로 보입니다 .)

유일한 객관적인 사실은 복제 goto가 기능을 조기에 종료한다는 것입니다. 코드를 살펴보면 동일한 결과를 초래할 수있는 유일한 단일 명령문이 리턴 일 것입니다.

이 오류는 기능에 SSLEncodeSignedServerKeyExchange()에서 이 파일 :

    if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) != 0)
        goto fail;
    if ((err =...) !=0)
        goto fail;
    if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
        goto fail;
        goto fail;  // <====OUCH: INDENTATION MISLEADS: THIS IS UNCONDITIONDAL!!
    if (...)
        goto fail;

    ... // Do some cryptographic operations here

fail:
    ... // Free resources to process error

실제로 조건부 블록을 둘러싼 중괄호는 버그를 방지 할 수있었습니다.
컴파일시 구문 오류 (따라서 수정) 또는 중복 무해한 이동으로 이어질 수 있습니다. 그건 그렇고, GCC 6은 일관성없는 들여 쓰기를 감지하는 옵션 경고 덕분에 이러한 오류를 발견 할 수 있습니다.

그러나 처음에는 더 구조화 된 코드로 이러한 모든 문제를 피할 수있었습니다. 따라서 goto는 최소한이 버그의 원인입니다. 그것을 피할 수있는 최소한 두 가지 방법이 있습니다.

접근법 1 : if 절 또는 중첩 ifs

오류에 대한 많은 조건을 순차적으로 테스트하는 대신 fail문제가 발생한 경우 레이블로 보낼 때마다 if잘못된 전제 조건이없는 경우에만 암호화 작업을 수행하도록 선택할 수 있습니다 .

    if ((err = ReadyHash(&SSLHashSHA1, &hashCtx)) == 0 &&
        (err = ...) == 0 ) &&
        (err = ReadyHash(&SSLHashSHA1, &hashCtx)) == 0) &&
        ...
        (err = ...) == 0 ) )
    {
         ... // Do some cryptographic operations here
    }
    ... // Free resources

접근 방식 2 : 오류 누산기 사용

이 접근법은 여기의 거의 모든 명령문이 err오류 코드 를 설정하는 함수를 호출하고 err0 인 경우에만 나머지 코드를 실행 한다는 사실을 기반으로합니다 (즉, 오류없이 실행 된 함수). 안전하고 읽기 쉬운 좋은 대안은 다음과 같습니다.

bool ok = true;
ok =  ok && (err = ReadyHash(&SSLHashSHA1, &hashCtx))) == 0;
ok =  ok && (err = NextFunction(...)) == 0;
...
ok =  ok && (err = ...) == 0;
... // Free resources

여기에는 단일 goto가 없습니다. 실패 종료 지점으로 빠르게 이동할 위험이 없습니다. 그리고 시각적으로 잘못 정렬 된 선이나 잊혀진 부분을 쉽게 발견 할 수 있습니다 ok &&.

이 구조는 더 간결합니다. C에서 논리의 두 번째 부분과 ( &&)은 첫 번째 부분이 참인 경우에만 평가 된다는 사실에 근거 합니다. 실제로 최적화 컴파일러에 의해 생성 된 어셈블러는 gotos가 포함 된 원래 코드와 거의 동일합니다. 옵티마이 저는 조건 체인을 매우 잘 감지하고 코드를 생성합니다. 처음에는 null이 아닌 반환 값이 끝으로 이동합니다 ( online proof ).

테스트 단계에서 ok 플래그와 오류 코드 사이의 불일치를 식별 할 수있는 기능 종료시 일관성 검사를 예상 할 수도 있습니다.

assert( (ok==false && err!=0) || (ok==true && err==0) );

실수 ==0!=0또는 논리적 커넥터 오류 로 대체 된 실수 는 디버깅 단계에서 쉽게 발견됩니다.

말했듯이 : 나는 대체 구문이 버그를 피했다고 가정하지 않습니다. 나는 그들이 버그를 더 어렵게 만들 수 있다고 말하고 싶습니다.


34
Apple goto fail 버그는 if 문 뒤에 중괄호를 포함하지 않기로 결정한 영리한 프로그래머로 인해 발생했습니다. :-) 따라서 다음 유지 보수 프로그래머 (또는 동일한 차이점)가 와서 if 문이 true로 평가 될 때만 실행되어야하는 또 다른 코드 행을 추가 할 때마다 명령문이 실행되었습니다. Bam, "goto fail"버그는 주요 보안 버그였습니다. 그러나 본질적으로 goto 문이 사용되었다는 사실과 관련이 없습니다.
Craig

47
Apple "goto fail"버그는 코드 줄이 중복되어 직접 발생했습니다. 해당 버그 의 특수 효과는 해당 줄이 goto중괄호가없는 if명령문 으로 인해 발생했습니다 . 그러나 goto코드 를 피 하면 무작위로 복제 된 줄의 영향에 대한 코드를 면역 할 것이라고 제안하는 경우 나쁜 소식이 있습니다.
immibis

12
부울 연산자 단축키를 사용하여 부작용을 통해 명령문을 실행하고 명령문보다 명확하다고 주장하고 if있습니까? 즐거운 시간. :)
Craig

38
"goto fail"대신 "failed = true"라는 문구가 있었다면 정확히 같은 일이 일어 났을 것입니다.
gnasher729 8

15
이 버그는 조잡한 개발자가 자신의 작업에주의를 기울이지 않고 자신의 코드 변경 사항을 읽지 않아 발생했습니다. 더 이상 아무것도 없습니다. 좋아, 아마도 거기에 약간의 테스트 감독을 던질 수도 있습니다.
밝기 경주 궤도에

34

유명한 Dijkstra 기사는 일부 프로그래밍 언어가 실제로 여러 개의 진입 점과 출구 점을 갖는 서브 루틴을 작성할 수있는 시점에 작성되었습니다 . 다시 말해서, 실제로 함수의 중간으로 뛰어 들어가서 실제로 함수를 호출하거나 일반적인 방식으로 함수를 반환하지 않고 함수 내의 어느 곳 으로든 뛰어 넘을 수 있습니다. 그것은 여전히 ​​어셈블리 언어에 해당됩니다. 아무도 그러한 접근 방식이 현재 우리가 사용하는 소프트웨어 작성 방식보다 우수하다고 주장하는 사람은 없습니다.

대부분의 현대 프로그래밍 언어에서 함수는 하나의 진입 점과 하나의 출구 점 으로 매우 구체적으로 정의됩니다 . 진입 점은 함수에 매개 변수를 지정하고 호출하는 지점이며, 종료점은 결과 값을 리턴하고 원래 함수 호출 다음의 명령에서 실행을 계속하는 지점입니다.

그 기능 내에서, 당신은 이유 내에서 원하는 것을 할 수 있어야합니다. 기능에 goto 또는 두 개를 넣으면 속도가 명확하거나 향상되면 왜 안됩니까? 함수의 요점은 명확하게 정의 된 약간의 기능을 격리하여 더 이상 내부적으로 작동하는 방식에 대해 생각할 필요가 없다는 것입니다. 일단 작성되면 사용하면됩니다.

그리고 네, 함수 내에 여러 개의 return 문을 가질 수 있습니다. 올바른 함수에는 항상 하나의 위치가 있습니다 (기본적으로 함수의 뒷면). 제대로 돌아갈 기회를 갖기 전에 goto로 함수에서 뛰어 내리는 것과 전혀 다릅니다.

여기에 이미지 설명을 입력하십시오

따라서 실제로 goto를 사용하는 것이 아닙니다. 학대를 피하는 것입니다. 누구나 gotos를 사용하여 몹시 복잡한 프로그램을 만들 수 있다는 데 동의하지만, 기능을 남용하여 동일한 작업을 수행 할 수도 있습니다 (gosto를 남용하는 것이 훨씬 쉽습니다).

가치있는 것을 위해, 줄 번호 스타일의 BASIC 프로그램을 파스칼 및 중괄호 언어를 사용한 구조적 프로그래밍에 이르기까지 졸업 한 이래로 고토를 사용할 필요가 없었습니다. 내가 하나를 사용하고 싶은 유일한 시간은 중첩 루프에서 조기 종료를하는 것입니다 (루프에서 다중 레벨 초기 종료를 지원하지 않는 언어로)하지만 일반적으로 더 깨끗한 다른 방법을 찾을 수 있습니다.


2
의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
maple_shaft

11

“goto”진술로 어떤 종류의 버그가 발생합니까? 역사적으로 중요한 예가 있습니까?

나는 gotofor 및 while 루프를 얻는 간단한 방법으로 자식으로 BASIC 프로그램을 작성할 때 문장 을 사용했습니다 (Commodore 64 BASIC에는 while 루프가 없었으며 for 루프의 올바른 구문과 사용법을 배우기에는 너무 미숙했습니다 ). 내 코드는 종종 사소한 것이었지만 모든 루프 버그는 즉시 goto 사용으로 인한 것일 수 있습니다.

저는 이제 고토 (goto)가 필요 없다고 판단한 고급 프로그래밍 언어 인 Python을 주로 사용합니다.

Edsger Dijkstra가 1968 년에 "Goto가 해로운 것으로 간주된다"고 선언했을 때, 관련 버그가 고토에서 비난받을 수있는 몇 가지 예를 제시하지 않았으며, 이는 더 높은 수준의 언어goto 에는 불필요하며 무엇을 위해 피해야한다고 선언했습니다 우리는 오늘날 일반적인 제어 흐름 인 루프와 조건을 고려합니다. 그의 말 :

이동을 제한없이 사용 하면 프로세스 진행 상황을 설명 할 의미있는 좌표 세트를 찾기가 매우 어려워집니다.
[...] 로 이동 약자로 문은 너무 원시적이다; 프로그램을 엉망으로 만드는 것은 너무 많은 초대입니다.

그는 코드를 디버깅 할 때마다 버그의 예를 산으로 만들었 goto습니다. 그러나 그의 논문은 goto고급 언어에는 불필요 하다는 증거로 뒷받침되는 일반화 된 입장 진술 이었습니다. 일반적인 버그는 문제의 코드를 정적으로 분석하는 능력이 없을 수 있다는 것입니다.

코드는 goto명령문 으로 정적 분석하기가 훨씬 어렵습니다 . 특히 제어 흐름 (이전에 사용했던)으로 돌아가거나 관련이없는 코드 섹션으로 이동하면 더욱 그렇습니다. 코드는 이런 식으로 작성 될 수있었습니다. 매우 부족한 컴퓨팅 리소스와 시스템의 아키텍처에 맞게 고도로 최적화되었습니다.

외경의 예

관리자가 매우 우아하게 최적화되었지만 코드의 특성으로 인해 "수정" 할 수없는 블랙 잭 프로그램이있었습니다 . 그것은 gotos에 크게 의존하는 머신 코드로 프로그래밍 되었으므로이 이야기는 매우 관련이 있다고 생각합니다. 이것은 내가 생각할 수있는 가장 좋은 정식 예입니다.

반대의 예

그러나 CPython의 C 소스 (가장 일반적이고 참조적인 Python 구현)는 goto명령문을 사용 하여 큰 영향을줍니다. 함수 내부의 관련없는 제어 흐름을 우회하여 함수의 끝 부분에 도달하여 가독성을 잃지 않고 기능을보다 효율적으로 만드는 데 사용됩니다. 이것은 구조적 프로그래밍 의 이상 중 하나를 존중 합니다. 함수에 대한 단일 종료 점이 있습니다.

기록을 위해,이 반례는 정적으로 분석하기가 매우 쉽다는 것을 알았습니다.


5
내가 만난 "멜 스토리 (Story of Mel)"는 (1) 모든 기계 언어 명령이 작동 후 이동을 수행하는 이상한 아키텍처에 있었고, (2) 연속 메모리 위치에 일련의 명령을 배치하는 것은 매우 비효율적이었습니다. 그리고이 프로그램은 컴파일 된 언어가 아닌 수동 최적화 어셈블리로 작성되었습니다.

@MilesRout 여기에서는 정확하다고 생각하지만 구조화 된 프로그래밍에 대한 wikipedia 페이지는 다음과 같이 말합니다. "많은 언어에서 발견되는 가장 일반적인 편차는 서브 루틴에서 조기 종료하기 위해 return 문을 사용하는 것입니다. , 구조화 된 프로그래밍에 필요한 단일 종료점 대신 " -이게 틀렸다고 말하는거야? 인용 할 출처가 있습니까?
Aaron Hall

@AaronHall 원래 의미가 아닙니다.
Miles Rout

11

wigwam 이 현재 건축 예술이었을 때 , 그들의 건축업자는 의심 할 여지없이 가발의 구성, 연기 탈출 방법 등에 관한 실질적인 조언을 줄 수있었습니다. 다행히 오늘날의 빌더는 아마도 그 조언을 대부분 잊어 버릴 수 있습니다.

역마차 가 현재의 교통 기술이었을 때, 운전자는 역마차 말, 고속도로 직원 을 방어하는 방법 등에 관해 실질적인 조언을 할 수있을 것입니다. 운 좋게도 오늘날 운전자는 그 조언을 대부분 잊어 버릴 수 있습니다.

펀치 카드 가 현재의 프로그래밍 기술이었을 때 , 실무자들은 마찬가지로 카드 구성, 문장 번호 매기기 등에 관한 실질적인 조언을 제공 할 수 있습니다. 나는 그 조언이 오늘날 매우 관련이 있는지 확실하지 않습니다.

당신은 "to statement to statement" 라는 문구를 알기에 충분히 나이가 있습니까? 당신은 그것을 알 필요는 없지만, 당신이 모르는 경우, 경고에 대한 경고 goto가 주로 관련된 역사적 맥락에 익숙하지 않습니다 .

오늘의 경고 goto는 그다지 중요하지 않습니다. 동안의 기본 교육과 함께 / 루프와 함수 호출을 위해, 당신도하지 않을 생각 를 _ 행 goto자주. 생각할 때 이유가있을 수 있으므로 계속 진행하십시오.

그러나 그 goto진술은 남용 될 수 없는가?

답 : 물론 악용 될 수는 있지만 상수가 제공 될 변수를 사용하거나 잘라 내기 및 붙여 넣기 프로그래밍과 같은 훨씬 일반적인 실수와 비교할 때 소프트웨어 공학에서 악용은 매우 작은 문제입니다. 리팩토링 무시로 알려진). 나는 당신이 많은 위험에 처해 있는지 의심합니다. longjmp원거리 코드로 제어를 사용 하거나 달리 전송 하지 않는 한 , 사용 goto하려고 생각 하거나 재미를 위해 그것을 시도하고 싶다면 계속하십시오. 너는 괜찮아 질거다.

당신은 악당 을 연기하는 최근의 공포 이야기가 부족하다는 것을 알 수 있습니다 goto. 이 이야기의 대부분 또는 전부는 30 세 또는 40 세인 것 같습니다. 그 이야기를 대부분 쓸모없는 것으로 여기면 당신은 확고한 입장에 서 있습니다.


1
나는 적어도 하나의 downvote를 끌었다는 것을 알았습니다. 글쎄요, 그것은 예상됩니다. 더 많은 다운 보트가 올 수 있습니다. 그러나 수십 년의 프로그래밍 경험으로 인해이 경우에는 기존의 대답이 잘못되었다고 가르쳤을 때 나는 전형적인 대답을하지 않을 것입니다. 여하튼 이것은 나의 견해이다. 나는 내 이유를 주었다. 독자가 결정할 수 있습니다.
thb

1
귀하의 게시물이 너무 나쁩니다. 의견을 무시할 수 없습니다.
Pieter B

7

goto진술 을 통해 다른 훌륭한 답변에 한 가지를 추가하려면 프로그램의 특정 위치에 어떻게 도달했는지 정확하게 말하기가 어려울 수 있습니다. 특정 라인에서 예외가 발생했음을 알 수 있지만 goto코드에가 있으면 전체 프로그램을 검색하지 않고 상태를 유발하는 예외를 발생시키기 위해 실행 된 명령문을 알 수있는 방법이 없습니다. 호출 스택 및 시각적 흐름이 없습니다. 1000 줄 떨어진 명령문이있을 수 있습니다. 잘못된 상태로 실행 goto하면 예외를 일으킨 라인에 처할 수 있습니다.


1
Visual Basic 6 및 VBA에는 오류 처리가 어렵지만 On Error Goto errh을 사용 Resume하면 다시 시도 Resume Next하고 문제를 일으키는 줄을 건너 뛰고 Erl어떤 줄인지 알 수 있습니다 (줄 번호를 사용하는 경우).
Cees Timmerman

@CeesTimmerman Visual Basic을 거의 사용하지 않았습니다. 그것에 대해 의견을 추가하겠습니다.
qfwfq

2
@CeesTimmerman : 자체 오류 블록이없는 서브 루틴 내에서 오류가 발생하면 "재개"의 VB6 의미가 끔찍합니다. Resume시작부터 해당 기능을 다시 실행하고 Resume Next아직 작성되지 않은 기능의 모든 항목을 건너 뜁니다.
supercat

2
@supercat 내가 말했듯이, 그것은 고통 스럽습니다. 정확한 행을 알아야하는 경우 모두 번호를 매기거나 일시적으로 오류 처리를 사용하지 않고 On Error Goto 0수동으로 디버그해야합니다. Resume확인 Err.Number하고 필요한 조정을 한 후에 사용하도록되어 있습니다 .
Cees Timmerman 8

1
현대 언어에서는 레이블이 지정된 루프goto 로만 작동하며 레이블이 지정된 루프 로 대체 된 것으로 보입니다 .
Cees Timmerman

7

goto는 다른 형태의 흐름 제어보다 인간이 추론하기가 더 어렵습니다.

올바른 코드를 프로그래밍하는 것은 어렵습니다. 올바른 프로그램을 작성하는 것은 어렵고, 프로그램이 올바른지 결정하는 것이 어렵습니다.

원하는 것을 모호하게 코드를 작성하는 것은 프로그래밍에 관한 다른 모든 것에 비해 쉽습니다.

goto는 원하는 코드를 작성하여 일부 프로그램을 해결합니다. 정확성을 쉽게 확인하는 데 도움이되지는 않지만 대체 방법은 종종 있습니다.

goto가 적절한 솔루션 인 프로그래밍 스타일이 있습니다. 사악한 쌍둥이가 적합한 솔루션 인 프로그래밍 스타일도 있습니다. 이 두 가지 경우 모두, 이해하기 쉬운 패턴으로 사용하고 있는지 확인하기 위해 각별한주의를 기울여야하며, 정확성을 보장하기 위해 어려운 일을하고 있지 않은지 수동으로 확인해야합니다.

예를 들어, 코 루틴이라는 일부 언어의 기능이 있습니다. 코 루틴은 스레드없는 스레드입니다. 스레드가 실행되지 않은 실행 상태 당신은 그들에게 실행을 요청할 수 있으며, 그들은 자신의 일부를 실행 한 다음 흐름 제어를 넘겨 자신을 일시 중단 할 수 있습니다.

코토 틴을 지원하지 않는 언어 (C ++ pre-C ++ 20 및 C와 같은)에서 "Shallow"코 루틴은 gotos와 수동 상태 관리를 혼합하여 사용할 수 있습니다. "깊은"코 루틴 은 C 의 setjmplongjmp기능을 사용하여 수행 할 수 있습니다 .

코 루틴이 너무 유용하여 수동으로 신중하게 작성하는 것이 가치가있는 경우가 있습니다.

C ++의 경우 언어를 확장하여 지원할 수있을 정도로 유용합니다. goto의 수동 상태 관리가이를 작성하는 프로그래머를 허용, 제로 비용 추상화 계층 뒤에 숨겨진되고 없이 고토, 자신의 혼란을 증명해야하는 어려움 void**의 수동 건설 / 상태의 파괴 등은 올바른 것입니다.

goto는 whileor for또는 ifor 와 같은 상위 레벨 추상화 뒤에 숨겨집니다 switch. 이러한 높은 수준의 추상화는 정확하고 확인하기가 더 쉽습니다.

언어에 일부 언어가 누락 된 경우 (일부 현대 언어에 코 루틴이 누락 됨) 문제에 맞지 않는 패턴으로 확대하거나 goto를 사용하는 것이 대안이됩니다.

일반적인 경우 컴퓨터가 원하는 일을 모호하게하는 것은 쉽습니다 . 확실하게 강력한 코드를 작성하는 것은 어렵습니다 . Goto는 첫 번째 도움이 두 번째 도움보다 훨씬 더 많이 도움이됩니다. 따라서 "고토는 해로운 것으로 간주됩니다."는 버그를 추적하기가 깊고 어려운 코드를 피상적으로 "작동"하는 표시이기 때문입니다. 충분한 노력을 기울이면 "goto"를 사용하여 코드를 안정적으로 만들 수 있으므로 절대 규칙을 지키는 것은 잘못입니다. 그러나 경험 상으로는 좋은 것입니다.


1
longjmpC에서 스택을 setjmp부모 함수로 되 감을 때만 합법적입니다 . (여러 수준의 중첩에서 벗어나는 대신 루프 대신 함수 호출의 경우). 반환 된 함수에서 완료 된 longjjmp컨텍스트 setjmp는 합법적이지 않습니다 (대부분의 경우 실제로 작동하지 않는 것 같습니다). 나는 공동 루틴에 익숙하지 해요,하지만 사용자 공간 스레드와 유사한 공동 루틴의 당신의 묘사에서, 나는 그것뿐만 아니라 저장된-레지스터 컨텍스트로 자신의 스택을 필요가있다 생각하고, longjmp단지 당신이 등록 할 수 있습니다 별도의 스택이 아닌 절약.
Peter Cordes

1
아, 나는 googled를해야합니다 : fanf.livejournal.com/105413.html 은 코 루틴을 실행할 스택 공간을 만드는 것을 설명합니다. (내가 의심 한 것처럼 setjmp / longjmp를 사용하는 것 외에도 필요합니다)
Peter Cordes

2
@PeterCordes : 코드가 코 루틴으로 사용하기에 적합한 jmp_buff 쌍을 만들 수있는 수단을 제공 할 필요는 없습니다. 일부 구현에서는 표준에서 이러한 기능을 제공하도록 요구하지 않더라도 코드가 생성 할 수있는 수단을 지정합니다. 많은 경우에 jmp_buff는 다른 컴파일러간에 일관되게 작동하지 않을 수있는 불투명 한 구조이기 때문에 "표준 C"와 같은 기술에 의존하는 코드는 설명하지 않습니다.
supercat

6

http://www-personal.umich.edu/~axe/research/Software/CC/CC2/TourExec1.1.f.html 에서이 코드를 살펴보면 실제로는 큰 죄수의 딜레마 시뮬레이션에 포함되어 있습니다. 오래된 FORTRAN 또는 BASIC 코드를 본 적이 있다면 그렇게 드물지 않다는 것을 알게 될 것입니다.

C  Not nice rules in second round of tour (cut and pasted 7/15/93)
   FUNCTION K75R(J,M,K,L,R,JA)
C  BY P D HARRINGTON
C  TYPED BY JM 3/20/79
   DIMENSION HIST(4,2),ROW(4),COL(2),ID(2)
   K75R=JA       ! Added 7/32/93 to report own old value
   IF (M .EQ. 2) GOTO 25
   IF (M .GT. 1) GOTO 10
   DO 5 IA = 1,4
     DO 5 IB = 1,2
5  HIST(IA,IB) = 0

   IBURN = 0
   ID(1) = 0
   ID(2) = 0
   IDEF = 0
   ITWIN = 0
   ISTRNG = 0
   ICOOP = 0
   ITRY = 0
   IRDCHK = 0
   IRAND = 0
   IPARTY = 1
   IND = 0
   MY = 0
   INDEF = 5
   IOPP = 0
   PROB = .2
   K75R = 0
   RETURN

10 IF (IRAND .EQ. 1) GOTO 70
   IOPP = IOPP + J
   HIST(IND,J+1) = HIST(IND,J+1) + 1
   IF (M .EQ. 15 .OR. MOD(M,15) .NE. 0 .OR. IRAND .EQ. 2) GOTO 25
   IF (HIST(1,1) / (M - 2) .GE. .8) GOTO 25
   IF (IOPP * 4 .LT. M - 2 .OR. IOPP * 4 .GT. 3 * M - 6) GOTO 25
   DO 12 IA = 1,4
12 ROW(IA) = HIST(IA,1) + HIST(IA,2)

   DO 14 IB = 1,2
     SUM = .0
     DO 13 IA = 1,4
13   SUM = SUM + HIST(IA,IB)
14 COL(IB) = SUM

   SUM = .0
   DO 16 IA = 1,4
     DO 16 IB = 1,2
       EX = ROW(IA) * COL(IB) / (M - 2)
       IF (EX .LE. 1.) GOTO 16
       SUM = SUM + ((HIST(IA,IB) - EX) ** 2) / EX
16 CONTINUE

   IF (SUM .GT. 3) GOTO 25
   IRAND = 1
   K75R = 1
   RETURN

25 IF (ITRY .EQ. 1 .AND. J .EQ. 1) IBURN = 1
   IF (M .LE. 37 .AND. J .EQ. 0) ITWIN = ITWIN + 1
   IF (M .EQ. 38 .AND. J .EQ. 1) ITWIN = ITWIN + 1
   IF (M .GE. 39 .AND. ITWIN .EQ. 37 .AND. J .EQ. 1) ITWIN = 0
   IF (ITWIN .EQ. 37) GOTO 80
   IDEF = IDEF * J + J
   IF (IDEF .GE. 20) GOTO 90
   IPARTY = 3 - IPARTY
   ID(IPARTY) = ID(IPARTY) * J + J
   IF (ID(IPARTY) .GE. INDEF) GOTO 78
   IF (ICOOP .GE. 1) GOTO 80
   IF (M .LT. 37 .OR. IBURN .EQ. 1) GOTO 34
   IF (M .EQ. 37) GOTO 32
   IF (R .GT. PROB) GOTO 34
32 ITRY = 2
   ICOOP = 2
   PROB = PROB + .05
   GOTO 92

34 IF (J .EQ. 0) GOTO 80
   GOTO 90

70 IRDCHK = IRDCHK + J * 4 - 3
   IF (IRDCHK .GE. 11) GOTO 75
   K75R = 1
   RETURN

75 IRAND = 2
   ICOOP = 2
   K75R = 0
   RETURN

78 ID(IPARTY) = 0
   ISTRNG = ISTRNG + 1
   IF (ISTRNG .EQ. 8) INDEF = 3
80 K75R = 0
   ITRY = ITRY - 1
   ICOOP = ICOOP - 1
   GOTO 95

90 ID(IPARTY) = ID(IPARTY) + 1
92 K75R = 1
95 IND = 2 * MY + J + 1
   MY = K75R
   RETURN
   END

여기 GOTO 문을 넘어서는 많은 문제가 있습니다. 나는 솔직히 GOTO 진술이 약간의 희생양이라고 생각합니다. 그러나 제어 흐름은 여기에서 절대적으로 명확하지 않으며 코드는 진행 상황을 매우 명확하게 만드는 방식으로 함께 혼합됩니다. 주석을 추가하거나 더 나은 변수 이름을 사용하지 않더라도이를 GOTO가없는 블록 구조로 변경하면 훨씬 읽고 쉽게 읽을 수 있습니다.


4
너무 참 :-) 언급 할 가치가 있습니다. 레거시 FORTAN과 BASIC에는 블록 구조가 없었으므로 THEN 절을 한 줄로 유지할 수없는 경우 GOTO가 유일한 대안이었습니다.
Christophe

숫자 대신 텍스트 레이블 또는 번호가 매겨진 줄에 대한 주석은 많은 도움이 될 것입니다.
Cees Timmerman

FORTRAN-IV 시절로 돌아 가기 : IF / ELSE IF / ELSE 블록, WHILE 루프 및 BREAK 및 NEXT 루프를 구현하기 위해 GOTO 사용을 제한했습니다. 누군가 나에게 스파게티 코드의 악함을 보여 주었고 왜 GOTO로 블록 구조를 구현해야하더라도 그것을 피하기 위해 구조화 해야하는 이유가 있습니다. 나중에 전 처리기 (RATFOR, IIRC)를 사용하기 시작했습니다. Goto는 본질적으로 악이 아니며 어셈블러 분기 명령에 매핑되는 지나치게 강력한 저수준 구성입니다. 언어가 부족하여 언어를 사용해야하는 경우 언어를 사용하여 적절한 블록 구조를 작성하거나 보강하십시오.
nigel222

@CeesTimmerman : 그것은 정원의 다양한 FORTRAN IV 코드입니다. FORTRAN IV에서는 텍스트 레이블이 지원되지 않았습니다. 최신 버전의 언어가 지원하는지 여부를 모르겠습니다. 표준 FORTRAN IV에서는 코드와 동일한 행에 대한 주석이 지원되지 않았지만이를 지원하기 위해 공급 업체별 확장이있을 수 있습니다. 나는 "현재"FORTRAN 표준이 무엇을 말하는지 모른다 : 나는 오래 전에 FORTRAN을 버렸고 그것을 놓치지 않았다. (내가 본 가장 최근의 FORTRAN 코드는 1970 년대 초 PASCAL과 매우 유사하다.)
John R. Strohm

1
@CeesTimmerman : 공급 업체별 확장. 일반적으로 코드는 주석에 부끄러워합니다. 또한 CONTINUE 및 FORMAT 문에만 줄 번호를 지정하여 나중에 줄을 쉽게 추가 할 수 있도록하는 규칙이 있습니다. 이 코드는 해당 규칙을 따르지 않습니다.
John R. Strohm 2009 년

0

유지 관리 가능한 프로그래밍의 원칙 중 하나는 캡슐화 입니다. 요점은 정의 된 인터페이스와 해당 인터페이스 만 사용하여 모듈 / 루틴 / 서브 루틴 / 컴포넌트 / 객체와 인터페이스하고 결과를 예측할 수 있다는 것입니다 (단위가 효과적으로 테스트되었다고 가정).

단일 코드 단위 내에서도 동일한 원칙이 적용됩니다. 구조화 된 프로그래밍 또는 객체 지향 프로그래밍 원칙을 일관되게 적용하면 다음과 같은 이점이 없습니다.

  1. 코드를 통해 예기치 않은 경로를 만듭니다.
  2. 정의되지 않거나 허용 할 수없는 변수 값이있는 코드 섹션에 도착
  3. 정의되지 않거나 허용 할 수없는 변수 값으로 코드 경로를 종료
  4. 거래 단위를 완료하지 못함
  5. 코드 제어 경로가 장치를 종료 할 때이를 해제하는 명시 적 구성을 사용하여 릴리스를 알리지 않았으므로 실제로는 죽었지 만 가비지 정리 및 재 할당에는 적합하지 않은 코드 또는 데이터의 일부를 메모리에 남겨 두십시오.

이러한 처리 오류의 일반적인 증상 중 일부는 메모리 누수, 메모리 저장, 포인터 오버플로, 충돌, 불완전한 데이터 레코드, 레코드 추가 / 청구 / 삭제 예외, 메모리 페이지 오류 등입니다.

이러한 문제는 사용자 인터페이스 잠금, 점진적인 성능 저하, 불완전한 데이터 레코드, 트랜잭션 시작 또는 완료 불가능, 데이터 손상, 네트워크 중단, 정전, 임베디드 시스템 장애 (미사일 제어 손실) 등이 있습니다. 항공 교통 관제 시스템의 추적 및 제어 능력 상실, 타이머 오류 등. 카탈로그는 매우 광범위합니다.


3
goto한 번도 언급하지 않고 대답 했습니다. :)
Robert Harvey

0

goto 는 일반적으로 필요하지 않은 곳에서 사용되기 때문에 위험합니다. 필요하지 않은 것을 사용하는 것은 위험하지만, 고토 특히. Google에 goto로 인해 많은 오류가 발생하면 이는 사용하지 않는 이유가 아닙니다 (프로그래밍에 본질적인 언어 기능을 사용할 때 항상 버그가 발생 함). 에 고토 사용.


goto 를 사용하거나 사용하지 않는 이유 :

  • 루프가 필요한 경우 while또는 을 사용해야 for합니다.

  • 조건부 점프를 수행해야하는 경우 if/then/else

  • 절차가 필요한 경우 기능 / 방법을 호출하십시오.

  • 당신은 단지, 함수를 종료해야하는 경우 return.

내가 goto사용하고 올바르게 사용 하는 것을 손가락으로 볼 수 있습니다.

  • CPython
  • libKTX
  • 아마 몇 개 더

libKTX에는 다음 코드를 가진 함수가 있습니다

if(something)
    goto cleanup;

if(bla)
    goto cleanup;

cleanup:
    delete [] array;

goto언어가 C이므로이 위치 에서 유용합니다.

  • 우리는 기능 안에있다
  • 클린업 함수를 작성할 수 없습니다 (다른 범위로 들어가서 액세스 가능한 호출자 함수 상태를 만드는 것이 더 부담이기 때문에)

이 유스 케이스는 C에 클래스가 없기 때문에 유용하므로 정리하는 가장 간단한 방법은을 사용하는 것 goto입니다.

C ++에서 동일한 코드를 가지고 있다면 더 이상 갈 필요가 없습니다.

class MyClass{
    public:

    void Function(){
        if(something)
            return Cleanup(); // invalid syntax in C#, but valid in C++
        if(bla)
            return Cleanup(); // invalid syntax in C#, but valid in C++
    }

    // access same members, no need to pass state (compiler do it for us).
    void Cleanup(){

    }



}

어떤 종류의 버그가 발생할 수 있습니까? 아무것도. 무한 루프, 잘못된 실행 순서, 스택 스크류 ..

문서화 된 경우 : 고토의 잘못된 사용으로 인한 중앙 공격에 남자를 허용 SSL의 취약점 여기에 문서입니다

그것은 오타 오류이지만 코드가 다른 방식으로 구조화되어 있으면 제대로 테스트되면 그러한 오류가 불가능했을 수 있습니다.


2
"goto"의 사용이 SSL 버그와 전혀 관련이 없음을 명확하게 설명하는 한 가지 답변에 대한 의견이 많이 있습니다. 버그는 한 줄의 코드를 부주의하게 복제했기 때문에 한 번은 조건부로, 한 번은 무조건적으로 실행되었습니다.
gnasher729

그래, 나는 받아들이 기 전에 고토 버그의 더 나은 역사적 예를 기다리고있다. 말했다시피; 실제로 해당 코드 줄에 무엇이 있는지는 중요하지 않습니다. 중괄호가 없으면이를 실행하여 오류가 발생했을 수 있습니다. 그래도 궁금합니다. "스택 나사"란 무엇입니까?
Akiva

1
이전에 PL / 1 CICS에서 작업 한 코드의 예입니다. 프로그램은 단일 라인 맵으로 구성된 화면을 표시합니다. 화면이 돌아 왔을 때 화면에서 보낸지도 배열을 찾았습니다. 그 요소를 사용하여 하나의 배열에서 색인을 찾은 다음 해당 색인을 사용하여 GOTO를 수행하여 개별 맵을 처리 할 수 ​​있습니다. 전송 된 맵의 배열이 올바르지 않거나 손상된 경우 GOTO를 잘못된 레이블로 시도하거나 레이블 변수 배열이 끝난 후 요소에 액세스하여 충돌이 심화 될 수 있습니다. 사례 유형 구문을 사용하도록 다시 작성되었습니다.
킥 스타트
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.