[급합니다][C언어] 다음 함수가 왜 safe한건지 궁금합니다!!

조회수 1869회

이미지

저희 교수님께서 여기 이 그림에 보이는 오른쪽 아래 f4 함수가 compiler에서 warning을 띄우기는 하겠지만 그래도 safe한 코드라고 하시더라구요.. 제 생각에는 f4 함수의 호출이 끝나면 스택에서 제거되기 때문에 parameter의 주소값을 리턴하는 저런 함수는 미정의된 주소값을 가리켜서 굉장히 문제가 클거 같거든요??

혹시 저 코드가 왜 safe하다는 건지 이유를 아시는 분 계시면 답변 부탁드립니다!!

  • (•́ ✖ •̀)
    알 수 없는 사용자

1 답변

  • 글쎄요. 제생각에는 안전하지 않은 코드입니다. 경우에 따라 문제가 발생하지 않을 수 있습니다(인라인화). 하지만 문제가 발생하지 않는다는 것을 보장하지 않기 때문에 안전하다고 할순 없습니다.

    올려주신 코드를 GCC 7.2 에서 x86-64 용으로 컴파일할 경우 아래와 같은 결과를 얻을 수 있습니다. (https://godbolt.org/g/t8f2wr)

    f4(int, int):
      push rbp
      mov rbp, rsp
      mov DWORD PTR [rbp-4], edi
      mov DWORD PTR [rbp-8], esi
      mov edx, DWORD PTR [rbp-4]
      mov eax, DWORD PTR [rbp-8]
      cmp edx, eax
      jle .L2
      mov eax, 0
      jmp .L3
    .L2:
      mov eax, 0
    .L3:
      pop rbp
      ret
    

    여기서 주의깊게 보아야하는 부분은 아래와 같습니다.

      cmp edx, eax
      jle .L2
      mov eax, 0
      jmp .L3
    .L2
      mov eax, 0
    

    edxeax (호출 인자의 값이 저장되어 있음) 를 비교하여 결과에 맞게 .L2 또는 .L3 로 점프하게 되는데, 조건의 참이냐 거짓이냐에 상관없이 mov eax, 0 를 수행하게 됩니다.

    이 명령어는 eax 레지스터에 0 값을 저장하며, eax 는 함수의 반환 값을 전달하기 위한 레지스터 입니다.

    즉, f4 함수는 어셈블리 결과 무조건 0을 반환하게 되어, 말씀하셨던 의도와는 다른 동작을 하게됩니다.

    함수 작성자의 의도와 실제 동작이 다르므로, 이는 안전하지 않은 함수입니다.

    그럼 왜 교수님께서는 컴파일러가 경고를 내지만 안전한 함수라고 말한것일 까요?

    그 이유중 하나는 컴파일러의 최적화 기능이 있기 때문입니다.

    경우에 따라 위의 f4 와 같은 함수는 인라인 화 되게 됩니다. 인라인 함수가 되면 호출을 하지 않고, 해당 함수를 호출한 곳에 그대로 붙여 넣게 됩니다. 이 경우 ab 는 스택에 생성되는 새로운 변수가 아닌 호출 인자로 사용한 변수가 될 수 있습니다. 그러면 반환하는 주소는 함수가 끝나도 유효한 주소를 나타낼 수 있습니다.

    하지만 이는 컴파일러마다 가능할 수 도있고, 아닐 수 도있습니다. 인라인화가 된다 하더라도, 해당 동작은 의도되로 동작할 수 있고 하지 않을 수 있습니다.

    이러한 것을 undefined behavior 라 부르며, 안전하지 않습니다.

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)