2019년 4월 29일 월요일

왜 goto문을 사용하는 것이 해로운가?에 대한 글들

사실 교재나 강의에서 goto문이 해롭다고만 했지
왜? 에 대해서는 알아볼 생각을 못했던 것 같다.

찾아보니 다음 글에서 Dijkstra님께서 프로그래머로서의 goto문 사용에 대해서 언급 하시고 이것이 발단되어 많은논쟁들이 있었고 지금의 구전과 같이 전달되고 있었음.

Go To Statement Considered Harmful, Edsger W. Dijkstra, 1968년
http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html

영어라서 천천히 읽어 보면 그냥 goto문을 사용하지 말라는 것이 아니지만 goto문을 사용하는 것은 프로그래머로서 s/w 작성하는데 있어 goto문이 적절하지 않다는 얘기 같다.


이를 한글로 자세히 설명하는 글들은 다음과 같고 아랫글들을 읽어보니 이해가 쉽게 되었음.



일부 발췌함.

이 논문으로 인해 구조적 프로그래밍에 대한 관심이 크게 일기 시작했고, 여러 언어의 형성에 큰 영향을 끼쳤다. 이 논문이 나오고, 이후 10년도 넘게, 아니 지금까지도 이 논문에 대한 논쟁은 그치지 않고 있다. 이 논문의 핵심은 다음 두 문장에 잘 드러나고 있다. 

① 우리는(우리의 한계를 알고 있는 현명한 프로그래머처럼) 정적인 프로그램과 동적인 진행과정 간의 개념적인 간격을 최소화하기 위해 최선을 다해야 하고, 그렇게 해서 (텍스트 공간에 펼쳐진) 프로그램과 (시간상에 펼쳐진) 진행 과정 사이의 대응 관계가 가능한 한 명백하게 해야 한다. 

② 어떠한 구문(clause)이든, 프로그래머 독립적 좌표계(programmer independent coordinate system)가 진행과정을 여전히 유익하고 편리하게 설명해 줄 수 있어야 한다는 요구 사항을 만족시켜야 한다. 

...

독자들도 모두 동의하겠지만 이 논문은 단순히 ‘goto 문을 없애라’는 수준이 아니다. 다익스트라 스스로도 자신이 제안하는 구조적 프로그래밍이 단순히 goto 문 제거 정도로 도매급으로 팔리는 데 심한 불쾌감을 표현했다. 구조적 프로그래밍은 물론이고, 이 논문 역시 시간과 공간의 갭을 줄여 프로그래머가 실수를 덜하고 올바른 프로그램을 좀더 쉽게 만들게 도와주는 것이 중요하다고 역설한다. 

...

이 논문의 결론이 현재 어느 정도나 실현됐을까? 일단, 대부분의 언어에서는 goto를 흡수하여 상위 수준의 제어문인 break, continue, exception 등을 지원하게 됐다. 덕분에 우리는 자신도 모르게 안전한 goto를 쓰고 있는 셈이다. 하지만 여전히 goto를 쓰는 언어가 남아 있다. 아직 논쟁은 그치지 않았다. 영원히 끝나지 않을지도 모르겠다. 

2019년 4월 26일 금요일

include, extern C, naming mangling, linking error

얼마 전 cpp 파일에서 header를 include 하지 않아서 linking error가 발생한 적이 있어 이에 대해서 찾아봤는데, 찾아보니 간단한 이유였었음.
아무래도 내가 C/C++ 수업에서 설명을 들었을 것 같은데 제대로 공부하지 않고 아무 생각 없이 코딩했던 내가 한심했음.

먼저 위의 현상이 발생한 원인을 예를 들어 설명하면
a.cpp 파일에서 정의된 test() 함수를 a.h에서 c-style(extern "C")로 선언을 하고
test() 함수를 b.cpp에서 사용하고 있는 상황에서
a.cpp에서 a.h를 include 하지 않으면 test() 함수 naming mangling으로
b.cpp에서 찾을 수 없는 상황이 되어 linking error가 발생하는 것이었음.

덕분에 아래 내용도 알게 되었으니 위안으로 삼자..

그리고 아래 내용은 모두 이 책에 정리되어 있음.
http://www.yes24.com/Product/Goods/23441719?scode=032&OzSrank=1

---------------------------------------------------------------------------------------------
https://stackoverflow.com/questions/48211215/how-is-the-header-file-connected-to-the-corresponding-cpp-file

cpp 파일 컴파일 시 header의 선언들에 대한 정의의 위치를 symbol table에 저장하고 컴파일 단위인 transition unit에서 찾지 못한 선언의 경우도 함께 저장한다.
cpp 파일이 모두 컴파일되고 linking 단계에서 모든 transition unit의 symbol table을 모아서 찾지 못한 선언의 정의도 업데이트하게 된다고 한다.


추가로 MS Visual C++ language guide에서 컴파일 방법과 참조 범위를 설명하고 있는데
https://docs.microsoft.com/en-us/cpp/cpp/program-and-linkage-cpp?view=vs-2019

컴파일 단계에서 각 cpp에 대해서
cpp와 cpp에서 include하는 모든 header를 묶어서 translation unit으로 만든다고 하고
각 translation unit은 독립적이라 compile 시 영향을 주지 않는다고 함.

전역이나 namespace scope에 정의된 function이나 non-const 전역 변수들은 External linkage라고 하며 모든 translation unit에서 참조가 가능하지만
다른 object(variable, class definition 등)는 Internal linkage라 불리며 해당 object가 정의된 translation unit에서만 참조 가능하다고 함.


위에서 설명된 symbol table에 대해서 여러 사례로 보여주고 설명하는 article이다.
https://www.toptal.com/c-plus-plus/c-plus-plus-understanding-compilation
Symbol table, naming mangling, undefined symbol, header guard, pass by value/reference 등에 대해서 실제 예를 들며 자세히 설명하고 있음.