Open muzigae opened 7 months ago
올바른 C 프로그램에선 extern
을 이용해 선언한 변수는 실제 정의가 있어야 하는데, 배포한 테스트 프로그램들에는 변수의 실제 정의가 없기 때문에 생기는 문제입니다. 일반적인 C 컴파일러에서는 링킹 오류로 컴파일이 안 되는 것이 정상입니다.
extern
을 지우면 clang 등을 이용해 컴파일이 가능합니다.
모든 소스 파일을 테스트할 수 있는 게 아니었군요. 감사합니다. benchmarks에서 extern이 포함된 모든 .c파일을 수정하여 컴파일까지는 성공했습니다. 다음으로 실행을 체크하는데 anagram에서 segmentation fault가 발생했습니다. 혹시 benchmarks에 있는 소스들은 코드의 정당성이 제대로 검증되지 않은 상태가 맞을까요?
그리고 한 가지 더 궁금한 것이 있는데 깃헙 액션이 private repository에 대해서는 사용량이 어느 정도 이상부터 유료던데 저희 프로젝트 정도로는 무료 한도 내에서 충분히 다 할 수 있는 것인지 궁금합니다.
배포된 소스들은 모두 제대로 작성된 프로그램입니다.
clang으로 컴파일하는 경우 read()
, write()
함수의 구현이 존재하지 않아 segmentation fault가 발생할 수 있습니다. 적절한 구현을 포함하여 소스코드를 수정해보시길 바랍니다.
Private repo의 경우 1개월에 2000분까지 Action 인스턴스 사용 시간이 주어지는데, cache 등을 잘 이용해 CI를 적절히 구성하면 4명이 작업하는 데는 충분할 것으로 보입니다.
혹시 그럼
더하여 CI/CD가 꼭 갖고 있어야할 기능 중 pass를 PR하여 추가했을 때 이전의 테스트와 PR에 포함된 테스트를 모두 통과하는지 체크하여야 한다고 하셨는데, 아직 pass를 만들거나 pass를 위한 테스트를 만들어보지 않아서 금요일까지 구축해야 하는 CI/CD에 이에 대해서는 기능상으로 문제가 없다고 판단되는 코드를 작성해 놓은 후, 추후 오류가 생긴다면 수정을 해도 되는지 궁금합니다. (컴파일러 빌드, 컴파일러 테스트, Alive2 테스트와 별개로 이것에 대해서만 여쭤봅니다.)
벤치마크 프로그램은 필요한 대로 수정 및 추가하셔도 됩니다. 채점 대상은 아니지만, 최적화 패스의 정확성 확인에 도움이 되는 방향으로 잘 구성하시면 결과적으론 이득이라 할 수 있겠습니다.
CI 구성을 Sprint 0까지 완성하지 못했다면, NFC를 동원해 첫 번째 최적화 패스 PR을 merge하는 시점 전까지 수정하는 방법도 있습니다. 패스 PR을 merge하는 시점에 제대로 구성된 CI를 통과하는지가 채점 요소이므로 이런 식으로 해도 감점은 피할 수 있으나, Sprint 1 기간 일부를 손해보는 것은 감수하셔야 할 것 같습니다. 테스트 파이프라인이 잘 동작하는지 확인이 필요하다면 아주 간단한 테스트 패스를 구현해 올려보는 것도 방법이 될 수 있겠습니다.
현재 test CI에 c-to-ll을 사용하려 테스트 중인데 clang으로 컴파일 했을 때는 문제가 없는 소스로 보입니다만 scanf 에러가 나옵니다. 검색해보니 함수 인라이닝으로 인한 문제라고 하는 것 같은데 어떻게 해결해야 하나요? clang에 -emit-llvm 옵션을 주면 정상적으로 생성을 하는데 주어진 스크립트 말고 이를 사용해도 문제가 없을까요? (interpreter에 해당 .ll 파일을 입력으로 주었을 때는 정상 작동하긴 합니다.)
c-to-ll.sh
스크립트는 단순히 C 파일을 .ll 파일로 변환하는 것 외에도 몇 가지 작업을 하기 때문에 clang만을 이용해 IR 프로그램을 emit하면 소개원실 컴파일러에서 제대로 컴파일되지 않을 수 있습니다.
scanf 에러라고 하면 혹시 정확히 어떤 문제실까요?
일단 주어진 벤치마크에 있는 프로그램 몇 개를 넣어봤을 때는 잘 되긴 했습니다만 그렇군요. 에러는 사진 상단에 있는 scanf has no body 라는 에러입니다. 주어진 벤치마크의 read 함수를 scanf를 통해 구현하였는데 이 부분에서 막히는 것 같습니다.
이렇게 정리할 수 있을 것 같습니다
read()
/ write()
함수를 scanf()
/ printf()
등으로 바꾼 뒤 clang
을 이용해 실행 파일 (바이너리) 로 컴파일하면 됩니다.c-to-ll.sh
에 넣어 IR 프로그램으로 변환한 뒤 소개원실 컴파일러를 통해 어셈블리 파일로 컴파일하면 됩니다.또한, 제공된 테스트 프로그램들의 경우는 각 input별로 정확한 output이 이미 포함되어 있으므로 굳이 따로 컴파일해 실행해보지 않고 output 파일과 비교만 해보셔도 됩니다.
주어진 benchmark의 ll 파일을 넣었을 때는 문제가 발생하지 않는 것을 확인하였습니다. 그러나 주어진 benchmark의 .c를 그대로 c-to-ll에 넣었을 경우 segmentation fault가 발생합니다. 전에 말씀해주신 대로 read, write의 구현이 필요한 것 같은데 scanf, printf 등을 배제하고 다른 I/O를 이용해 벤치마크를 수정해야 c-to-ll 사용이 가능한 것일까요? 만약 그렇다면 사용에 제한이 너무 큰 것 같은데 어떤 I/O 함수를 사용할 수 있고 어떤 건 사용할 수 없는지 알 수는 없을지 여쭤봅니다.
추가로 몇 가지 테스트 해봤는데 링커 문제인지 문제가 정확히 어떤 건지 모르겠습니다. puts, perror 등 헤더 파일에 들어있는 다른 함수 이용시 body가 없다며 호출되지 않고, errno.h를 넣어서 errno를 사용할 수 있는지도 봤는데 body가 없다며 c-to-ll이 제대로 된 파일 변환을 하지 못합니다. 헤더 파일에 있는 글로벌 변수와 함수들을 전혀 사용하지 못하는 것 같습니다.
https://github.com/snu-sf-class/swpp202401/issues/47#issuecomment-2082102549
현재 c-to-ll.sh
를 개발 서버에서 구동하면 segmentation fault가 발생합니다. 다소 번거롭겠지만 x86 환경에서 .ll 파일을 생성하셔야 할 것 같습니다.
c-to-ll.sh
에 넣을 C 프로그램은 benchmark 리포지토리에 있는 다른 C 프로그램들처럼
int64_t read();
void write(int64_t);
위 함수 선언이 반드시 필요합니다. printf, scanf 등 통상적인 C 프로그램에서 사용하는 (C 표준 라이브러리를 필요로 하는) 함수는 동작하지 않으니, 유의 부탁드립니다.
안녕하세요. 현재 CI로 benchmarks에 있는 모든 .c파일을 컴파일하여 input, output을 비교하는 코드를 작성 중입니다. binary_tree.c의 extern *root로 인해 위 에러가 발생하는데 추가적으로 링크해야 할 파일이 있는 것인지 컴파일러 빌드가 잘못된 것인지 궁금햡니다. anagram.c에서는 문제가 없는 것으로 보입니다.
감사합니다.