오늘은 C++ 로 작성 된 프로그램을 gtest 로 테스트하다가 문제가 발생했어요
내용: 구성 된 gtest 를 수행 시 segmentation fault 가 발생
조치: argv 를 사용하는 테스트가 초기화되지 않은 argv 를 사용. 초기 값 설정이 필요
결론적으로 Test 용도로 argv 를 임의로 설정해야 했습니다.
실제 프로그램에서는 프로그램 이름으로 argv[0] 이 들어오기 때문에, 테스트에서만 문제가 발생하는 경우였고, argc 가 0 보다 큰지 정도만 체크해도 됐지만, fake argument를 같이 넣어서 테스트를 다시 작성했습니다.
원래 있던 코드는 아래처럼 작성되어 있었어요.
#include <iostream>
using namespace std;
int main( int argc, char *argv[] ) {
cout << argc << endl;
for ( int i = 0; i < argc; i++ ) {
cout << argv[i] <<endl;
}
return 0;
}
argv 는 char *argv[] 또는 char **argv 로 main 함수에 전달되고 argc를 통해서 argv 갯수를 우리는 알 수 있어요
실행
$ ./a.out
1
./a.out
앞서 말했 듯이, gtest 에서는 argc 나 argv 가 전달되지 않았어요.
그래서 위의 코드랑 조금은 다른 상황이라고 볼 수 있죠.
argc = 0, argv 는 nullptr 인 상황이었고, Segmentation fault가 났던 이유는 이런 argv 포인터를 참조했기 때문이었죠.
오류코드
using namespace std;
class MyCommand {
char **myargv;
public:
MyCommand ( char *argv[] ) {
myargv = (char **)argv;
}
void doSomething() {
// Access to myargv
}
};
int main( int argc, char *argv[] ) {
cout << argc << endl;
for ( int i = 0; i < argc; i++ ) {
cout << argv[i] <<endl;
}
MyCommand *mc = new MyCommand ( argv );
mc->doSomething();
MyCommand *err_mc = new MyCommand ( nullptr );
err_mc->doSomething();
return 0;
}
위의 예시 코드를 실제로 실행했을 때 사실 오류는 안나옵니다.
그런데 doSomething에서 argv에 접근을 하려고 하면 메모리 접근에 문제가 생기는거죠.
그래서 nullptr가 들어올 수 있는 가능성을 배제하기 위해 아래와 같이 코드를 수정 해 주었습니다.
수정코드
19 int main( int argc, char *argv[] ) {
20
21 cout << argc << endl;
22 for ( int i = 0; i < argc; i++ ) {
23 cout << argv[i] <<endl;
24 }
25
26 if ( argv > 0 ) {
27 MyCommand *mc = new MyCommand ( argv );
28 mc->doSomething();
29
30 MyCommand *err_mc = new MyCommand ( nullptr );
31 err_mc->doSomething();
32 } else {
33 char *fake_argv[] = { (char*)"test.sh", NULL };
34
35 MyCommand *mc = new MyCommand ( fake_argv );
36 mc->doSomething();
37
38 MyCommand *err_mc = new MyCommand ( fake_argv );
39 err_mc->doSomething();
40 }
41
42 return 0;
43 }
argv 마지막은 NULL로 초기화 해 줍니다.
fake_argv에 인자가 하나밖에 없으니 필요에 따라 argc 도 1 로 변경 해 줍니다.
사실 일반적으로 argc 또는 argv 를 변경해야 할 이유가 없긴 합니다.
저같은 경우 command line ( argv[0] ) 을 프로세스 추적을 목적으로 변경이 필요했기 때문에 특정 클래스에서 접근이 필요 했으며,
해당 클래스를 테스트하는 도중에 gtest 에서 argument가 넘어오지 않아 임의로 세팅한 경우였습니다.
'CS' 카테고리의 다른 글
[CS/AWS] 아마존 웹 서비스 신규 계정생성과 Free Tier 이용하기 (0) | 2022.01.14 |
---|---|
[CS] 코드커버리지(Code coverage) 란? (0) | 2022.01.10 |
[Bash shell] Shell 에서 따옴표 없애는 방법 (0) | 2021.09.13 |
정규표현식 사용, 숫자 문자 포맷 체크하기 (0) | 2021.08.29 |
[Linux] vim editor 자동완성 활용하기 (0) | 2021.08.23 |