작성
·
339
0
안녕하세요 교수님,
이번 겨울 교수님 덕분에 C++ 공부 즐겁게 하고 있는 학생입니다.
다름이 아니오라 제가 이 코드를 실행하다가 막히는 부분이 있어서 질문드립니다.
우선 실행 환경은
- macOS Catalina
- CLion / Clang
입니다.
VS 위주로 수업이 진행되고, 이외의 플랫폼과 툴에 대해서는 답변이 어려울 수 있다는 말씀을 소개 페이지에 하셨지만 혹여나 제가 놓치고 있는 부분이 있을까 해서 질문 드립니다.
< 수정 >
main 함수 위쪽의
int Something::s_value = 1234; 로 변수의 값을 초기화 해주지 않은 걸 뒤늦게 발견했습니다.
_init 이라는 내부 클래스를 만들고, Something의 멤버 변수(?)로 s_initializer 라는 인스턴스를 생성한 이유가
이 인스턴스가 생성되면서 생성자가 호출 -> 생성자가 s_value를 9876이라는 값으로 초기화
인 것 같습니다만, s_initializer 호출 전에 s_value를 초기화시키지 않으면 아래의 오류가 발생하는 이유가 무엇인가요? (너무 질문이 길어져 죄송합니다...)
#include <iostream>
using namespace std;
class Something
{
public:
class _init // inner class
{
public:
_init() // constructor
{
s_value = 9876;
}
};
private:
static int s_value;
int m_value;
static _init s_initializer;
public:
Something() // constructor
: m_value(123)
{}
// static member function
static int getValue()
{
/*
* in static member function, you CANNOT use 'this pointer'
* since both static member variable & function are independent
* to the instances constructed using the class definition.
*/
return s_value;
}
};
// THIS IS NOT WORKING!!
Something::_init Something::s_initializer;
int main()
{
Something st1;
// cout << st1.getValue() << endl;
/* fptr -> temp
* and the function temp NEEDS 'this' pointer as its input.
*/
/* In contrast,
* static member functions are independent to the instances,
* since it has its own address on memory so we don't need to
* pass the pointer of instance('this') to it.
*/
int (*fptr2)() = &Something::getValue;
cout << (*fptr2)() << endl;
return 0;
}
위에 첨부해드린 코드를 실행시키면 다음과 같은 에러를 볼 수 있습니다.
< 에러 메시지 >
Undefined symbols for architecture x86_64:
"Something::s_value", referenced from:
Something::getValue() in main_8_11.cpp.o
Something::_init::_init() in main_8_11.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)getValue() 라는 정적 멤버 함수에 의해 정적 멤버 변수 s_value가 참조되는 과정에서, 이 변수를 컴파일러가 찾을 수 없다는 내용인 것 같습니다.(제가 생각한 게 맞나요?)
교수님의 강의 코드와 요점 정리를 해주신 분 블로그의 코드까지 참고해서 작성했는데도 오류가 사라지지 않아서 이렇게 질문을 드립니다.
추가적으로 문제 상황을 설명드리는데 있어 도움이 될까 싶어 한 가지 덧붙입니다:
Something::_init Something::s_initializer; (main 함수 위)
에서 s_initializer 아래 노란줄이 표시되는데, 커서를 갖다대면 이런 메시지가 나옵니다.
Clang-Tidy: Initialization of 's_initializer' with static storage duration may throw an exception that cannot be caught
교수님의 친절한 설명 덕분에 처음 배울 때엔 어렵게만 느껴졌던 참조자와 포인터 개념을 잡고 여기까지 올 수 있었습니다. 긴 질문 읽어주셔서 감사드립니다!
답변 2
3
static member variable은 별도로 초기화를 안해주면 메모리 배정이 안되어서 그런 문제가 생기는 것으로 기억합니다. 아래 링크 보시면 "implementation-defined manner" 라는 표현이 있는 것으로 봐서 OS나 컴파일러에 따라 달라질 수도 있으니 참고하세요.
https://stackoverflow.com/questions/3270427/when-is-memory-allotted-to-static-variables-in-c
0
읽어보니,
소스 코드에서 초기화가 되지 않은 static variable들은 BSS라고 하는 최하단의 메모리 영역으로 배정이 된다는 내용이고, 컴파일러마다 이런 할당을 처리하는 방식이 다르다는 것 같습니다.
이건 이후에 컴퓨터 시스템이나 OS같이 보다 근본적인 과목을 공부하면서 다시 살펴볼 필요가 있는 문제인 듯 싶네요.
덕분에 많은 것을 알아갑니다. 앞으로도 강의 열심히 듣겠습니다.
답변 감사합니다 :)