컴파일러는 오류와 경고를 어떻게보고해야합니까?


11

가까운 장래에 컴파일러를 작성할 계획은 없습니다. 아직도, 나는 컴파일러 기술에 관심이 있으며, 어떻게 이런 것들이 더 나아질 수 있는지에 관심이 있습니다.

컴파일 된 언어로 시작하면 대부분의 컴파일러에는 경고와 오류의 두 가지 오류 수준이 있습니다. 경고와 오류, 가장 치명적이지 않은 대부분의 경우 수정해야하는 오류 및 기계 (또는 바이트)를 생성 할 수없는 대부분의 시간을 나타내는 오류 입력에서 코드.

그러나 이것은 꽤 약한 정의입니다. Java와 같은 일부 언어에서는 @SuppressWarning지시문 을 사용하지 않고 특정 경고를 제거하는 것이 불가능합니다 . 또한 Java는 치명적이지 않은 특정 문제를 오류로 처리합니다 (예를 들어, Java의 연결할 수없는 코드는 알고 싶은 이유로 오류를 트리거합니다).

C #에는 동일한 문제가 없지만 몇 가지가 있습니다. 컴파일은 여러 패스에서 발생하는 것으로 보이며 패스가 실패하면 추가 패스가 실행되지 않습니다. 이 때문에 빌드가 실패 할 때 발생하는 오류 수는 종종 과소 평가됩니다. 한 번 실행하면 두 가지 오류가 있다고 말할 수 있지만 일단 수정하면 26 개의 새로운 오류가 발생합니다.

C와 C ++를 파는 것은 단순히 Java와 C #의 컴파일 진단 취약점에 대한 나쁜 조합을 보여줍니다 (Java와 C #이 각각 절반의 문제로 진행되었다고 말하는 것이 더 정확할 수도 있음). 일부 경고는 실제로 오류 (예 : 모든 코드 경로가 값을 반환하지 않을 때) 여야하지만 여전히 표준을 작성할 때 컴파일러 기술이 이러한 종류의 코드를 작성하기에 충분하지 않았기 때문에 경고입니다 필수 사항을 확인합니다. 같은 맥락에서, 컴파일러는 종종 표준보다 더 많은 사항을 확인하지만 추가 결과를 위해 여전히 "표준"경고 오류 수준을 사용합니다. 그리고 종종 컴파일러는 발견 할 수있는 모든 오류를보고하지 않습니다. 그것들을 모두 제거하려면 컴파일이 약간 필요할 수 있습니다. C ++ 컴파일러가 침을 뱉고 싶어하는 중대한 오류는 말할 것도없고,

이제 컴파일러가 경고를 낼 때 실패를보고하도록 많은 빌드 시스템을 구성 할 수 있다는 점을 추가하면 이상한 혼합이 발생합니다. 모든 오류가 치명적이지는 않지만 일부 경고가 발생합니다. 모든 경고를받을 자격이있는 것은 아니지만 더 이상 언급하지 않고 일부 경고를 명시 적으로 억제합니다. 때로는 모든 경고가 오류가됩니다.

컴파일되지 않은 언어에는 여전히 크 래피 오류보고 기능이 있습니다. 코드가 실제로 실행될 때까지 Python의 오타는보고되지 않으며 스크립트가 하나를 만나면 실행이 중지되므로 한 번에 두 개 이상의 오류를 발생시킬 수 없습니다.

PHP는 다소 심각한 오류 수준 예외가 있습니다. 구문 분석 오류는 한 번에 하나씩보고되며 경고가 너무 나빠서 스크립트를 중단해야하지만 (기본적으로는 아님), 알림은 종종 심각한 논리 문제를 표시합니다. 일부 오류는 실제로 스크립트를 중지 할만큼 나쁘지 않지만 여전히 PHP에는 평소와 같이 이상한 점이 있습니다 (실제로 치명적이지 않은 치명적 오류에 대해 오류 수준이 필요한 이유는 무엇입니까? E_RECOVERABLE_E_ERROR, 나는 당신에게 이야기하고 있습니다).

내가 생각할 수있는 컴파일러 오류보고의 모든 단일 구현이 망가진 것 같습니다. 모든 훌륭한 프로그래머가 오류를 올바르게 처리하는 것이 얼마나 중요한지 주장하지만 자체 도구를 얻을 수는 없기 때문에 정말 부끄러운 일입니다.

컴파일러 오류를보고하는 올바른 방법은 무엇이라고 생각하십니까?


-1 : "비 컴파일 언어는 여전히 크 래피 오류보고에 대한 점유율을 가지고 있습니다."주관적이고 논쟁 적입니다. 정말 도움이되지 않습니다. 이것이 질문입니까, 불만입니까?
S.Lott

2
@ S.Lott 나는 당신이 여기 가장자리에 조금 있다고 생각합니다. 나는 컴파일 된 언어에 훨씬 더 힘들었고, 당신을 귀찮게하는 것처럼 보이지 않았습니다.
zneak

@zneak : 다른 문장은 사실에 가깝고 구문 분석하기가 더 어렵습니다. 그 진술은 주관적이고 논쟁적인 것으로 가장 쉽게 드러났다.
S.Lott

1
@ S.Lott 파이썬이 한 번에 하나의 오류를 표시한다고 잘못 말하고 있습니까?
zneak

1
@ S.Lott 그러면 마지막으로 시도했을 때 구문 오류로 인해 Python이 "컴파일"하려고하지 않고 이름 오류로 인해 예외가 발생하고 함수의 나머지 부분을 확인하지 않기 때문에 상황이 변경되어야합니다 (이것은 그대로 두었습니다) 테스트 가능한 단위당 하나의 오류를보고 할 공간). 나의 주관적이고 논쟁적인 진술은 내가 사실이라고 생각한 것에 대한 소개 였지만, 그것이 사실이 아니라면 더 나아가서 내 질문을 편집 할 것입니다. 지금 어떻게 작동합니까?
zneak

답변:


6

귀하의 질문은 실제로 컴파일러 오류를보고 하는 방법 에 관한 것이 아니라 문제의 분류와 그에 대한 조치에 관한 것입니다.

경고 / 오류 이분법이 정확하다고 가정하여 시작하면, 그 위에 얼마나 잘 구축 할 수 있는지 봅시다. 몇 가지 아이디어 :

  1. 경고의 다른 "수준". 많은 컴파일러가이를 구현합니다 (예 : GCC에 경고 대상을 정확하게 구성하기위한 많은 스위치가 있음). 예를 들어보고 된 경고의 심각도보고 및 "경고"설정 기능과 같은 작업이 필요합니다. 지정된 심각도를 초과하는 경고에 대해서만 오류입니다.

  2. 오류 및 경고의 Sane 분류 코드가 사양을 충족하지 않아서 컴파일 할 수없는 경우에만 오류를보고해야합니다. 도달 할 수없는 명령문은 코딩 오류 일 수 있지만 오류가 아닌 경고 여야합니다. 코드가 여전히 "유효"하며 도달 할 수없는 코드로 컴파일하려는 합법적 인 인스턴스가 있습니다 (예 : 디버깅을위한 빠른 수정). .

이제 내가 당신에게 동의하지 않는 것들 :

  1. 모든 문제를보고하기 위해 추가 노력을 기울입니다. 오류가 있으면 빌드가 중단됩니다. 빌드가 깨졌습니다. 해당 오류가 수정 될 때까지 빌드가 작동하지 않습니다. 따라서 코드에 "잘못된"다른 모든 것을 시도하고 식별하기 위해 "계속"하는 대신 오류를 즉시보고하는 것이 좋습니다. 특히 어쨌든 초기 오류로 인해 많은 것들이 발생했을 때.

  2. 오류에 대한 경고의 특정 예. 예, 아마도 프로그래머의 실수 일 것입니다. 아니요, 빌드를 중단해서는 안됩니다. 함수에 대한 입력이 항상 값을 반환한다는 것을 알고 있다면 빌드를 실행하고 추가 검사를 추가하지 않고도 테스트를 수행 할 수 있어야합니다. 예, 경고해야합니다. 그리고 그 중 하나가 심각합니다. 그러나 오류 경고로 컴파일되지 않는 한 빌드 자체를 중단해서는 안됩니다.

생각?


동의하지 않는 부분을 제외하고는 귀하의 의견에 동의하므로 +1입니다. 정의되지 않은 동작의 경우 실제로 얼마나 나쁜지 고려할 때 모든 코드 경로가 값을 반환하거나 프로그램을 중단시키는 것이 쉽다고 생각합니다.
zneak

7

제기 한 한 가지 문제는 불완전한 오류보고 (예 : 2 개의 오류보고)였으며 문제를 해결하면 더 많은 문제가 발생합니다.

이것은 컴파일러 작성자의 타협입니다. 어떤 오류가 발생했는지에 따라 컴파일러 는 실제와 관련이 거의없는 오류를보고하기에 충분 하지 않은 것을 잘못 이해하기가 매우 쉽습니다 . 예를 들어, itn x;대신에 간단한 오타를 생각해보십시오 int x;. itn의미가 있는 다른 작업을 수행하지 않은 경우 이는 오류로보고됩니다. 괜찮아요.하지만 이제 다음에 일어날 일을 고려하십시오. 컴파일러는 변수 로 사용 하려는 많은 코드를 봅니다 x. A) 중지하고 문제를 해결하도록해야합니까, 아니면 B) error: "x": undeclared identifier해당 순서에 대해 2000 오류가 발생 했습니까? 다른 가능성을 고려하십시오.

int main()[

이것은 또 다른 명백한 오타입니다. 분명히 그것은 {대신에 있어야합니다 [. 컴파일러는 그 부분을 아주 쉽게 알 수 있습니다. 그러나 다음과 같은 x=1;말에 대한 오류를보고해야 error: statement only allowed inside a function합니까?

이것들은 상당히 사소한 문제입니다-훨씬 더 나쁜 문제는 쉽게 찾을 수 있습니다 (특히 우리가 알고있는 것처럼 C ++ 템플릿에 들어갈 때). 결론은 컴파일러 작성자가 일반적으로 잘못된 오류를보고하는 것 (즉, 문제가 있지만 오류로보고하는 것)과 실제 오류를보고하지 않는 것 사이의 절충을 시도하는 것입니다. 어느 방향 으로든 잘못 가고있는 것을 막기 위해 따라야 할 몇 가지 규칙이 있지만, 그 중 어느 것도 완벽에 가까운 곳은 없습니다.

언급 한 다른 문제는 Java와 @SupressWarning입니다. 이것은 위와는 상당히 다릅니다. 수정하기는 매우 쉽지 않습니다. 수정되지 않은 유일한 이유는 Java의 기본 "문자"와 맞지 않는다는 것입니다. 즉, "버그가 아니라 기능입니다." 그것은 일반적으로 농담이지만,이 경우 관련된 사람들은 너무 잘못 안내되어 실제로 그것이 사실이라고 믿습니다.

값을 반환하지 않는 코드 경로가있는 C 및 C ++에서 언급 한 문제는 실제로 원시 컴파일러를 허용하지 않습니다. 수십 년의 기존 코드 를 허용하기 위해 일부는 아무도 수정, 터치 또는 읽기를 원하지 않습니다. 그것은 오래되고 추악하지만 효과가 있으며 아무도 계속 일하기를 원하지 않습니다. 더 좋든 나쁘 든 언어위원회는 이전 버전과의 호환성을 유지하는 데 주력하고 있으므로 아무도 좋아하지 않는 것을 허용 하지만 일부 사람들은 (적어도 생각한다고 생각합니다) 허용합니다.


3
다른 많은 사람들을 유발하는 초기 오류에 대한 요점 외에도 나중에 패스가 성공적으로 완료되기 위해서는 나중에 패스가 만들어 지기도합니다. 예를 들어, C # 컴파일러의 초기 단계 중 하나는 상속 그래프에 사이클이 없는지 확인합니다. A에서 상속되는 A에서 B를 상속받지 않습니다. 계속해서 목록을 생성하려는 경우 그 이후의 모든 오류 중에서, 나중에 통과 할 때마다주기에 대처할 수 있어야하므로 "양호한"컴파일에서도 훨씬 느려집니다.
아논.

@곧. Java 컴파일러는 초기 패스 생존에 훨씬 더 많은 노력을 기울이고 있지만 크게 느리지는 않습니다. 나에게 그것은 얼마나 빨리 csc포기 하는지 짜증나게 한다.
zneak

@zneak : Jerry가 말했듯이 컴파일러 개발자들에게는 타협입니다. 좋은 오류 진단을 작성하는 것은 실제로 매우 어려운 문제입니다 (실제로 얼마나 멀리 갈 수 있는지에 대한 예는 clang 을보십시오). C # 컴파일러의 단계 및 단계에 대한 자세한 내용은 여기참조하십시오 .
Dean Harding
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.