작성자 없음
작성자 정보가 삭제된 글입니다.
작성
·
450
1
안녕하세요 ㅎㅎ
강의를 듣다가 여러 궁금증이 생겨 질문드립니다.
Q1. 메모리 할당에 관한 질문입니다.
질문드리기 앞서 무성의한 변수 작성에 사과드립니다.
static 변수(a)는 Data영역에
멤버변수(b)는 Heap영역에
멤버함수(Func)는 Code영역에
멤버함수 내에 존재하는 지역변수(c)와 t2는 Stack영역에
할당된다고 알고있습니다.
실제 Main에서 Test라는 클래스를 인스턴스화후에 메모리 구조에 대해서 몇 가지 질문드리고 싶습니다.
Test t2 = new Test(); 이 코드를 실행하게 되면
Stack에 t2라는 변수가 생기고 Heap에 할당된 메모리를 가리키고 있을거라 생각합니다. 궁금한건 Func함수입니다.
질문속의 작은 질문들을 정리해서 말씀드리면
Q1.1 t2라는 변수를 통해서 저희는 멤버변수인 b에도 접근하고 Func라는 함수도 호출합니다. 다만 t2는 heap의 주소를 가리키는 포인터인데 heap영역에 있지 않는 Func라는 함수를 어떻게 가리키는건가요? 한 가지 추정을 해보면 heap어딘가에 Func의 Stack 시작점 주소를 저장할 공간이 있고 Stack에 함수가 할당되면 그곳으로 매핑을 시켜주는 건가요?
Q1.2 Code영역이 궁금해서 검색하다가 지역변수는 함수 호출시에 Code영역에 저장되는 함수 정의를 활용하여 초기화 된다. 라는 글을 발견했습니다. Code영역에 함수가 정의된다는것과 Stack에 함수가 할당되는게 구체적으로 어떤 연관성이 있는지 이해가 잘 안됩니다.. 정의를 활용한다는게 어떤 의미안가요?
Q1.3 클래스 내부에서 Static Test t1 = new Test(); 코드를 실행해봤습니다. static변수는 클래스가 메모리에 올라갈때 할당 된다고 배웠는데 t1이라는 변수가 Data영역에 할당되자마자 Heap에도 데이터가 할당되는건가요?
Q1.4 이러한 메모리 할당에 대한 의문이 생기면 실제로 실험해보고 검증하고 싶은데 Stack Heap Data Code 영역을 실제로 확인할 수 있는 방법이 무엇인지 모르겠습니다 ㅠㅠ.. 디버깅처럼 이러한 것들을 확인할 수 있는 방법이 있을까요..??
Q2. ReaderWriterLock에 관한 질문입니다.
WriteUnLock 부분에서 Exchange를 사용하지 않고 _flag = EMPTY_Flag;를 해주면 문제가 발생할까요? 제 스스로 고민해본 결과 WriteUnLock은 어쨋든 Lock을 잡은 상태에서만 호출을 한다고 가정했으니 임계영역이 아니라고 생각했습니다.
재귀적으로 호출을 해도 별 문제가 없다고 생각한건 싱글스레드가 독보적으로 호출할 수 있는 영역이니까요. ReadUnLock의 경우는 여러 스레드가 동시에 값을 변경하니 Interlocked.Decrement(ref _flag);를 호출하는게 맞다고 생각하는데 WriteUnLock을 _flag = EMPTY_Flag;이와 같이 작성해도 별 문제가 없을까요?
답변 1
1
Q1)
클래스마다 함수 호출 테이블이 있는데
그 테이블을 참고해서 어떤 주소에 호출될 함수가 있는지 알 수 있습니다.
Q2)
함수를 작성하면 그 내용물이 컴파일 되어,
코드 영역에 명령어들이 들어가게 됩니다.
void Test()
{
int a = 3;
}
과 같이 했다면 코드 영역에 Test라는 함수 영역이 잡힐 것이고,
int a = 3;을 실행하기 위해 [스택 영역 몇 번에 있는 a 변수에 3을 대입하라]라는
예를 들면 어셈블리 기준으로 mov [a], 3과 같은 명령어가 만들어집니다.
이게 instruction opcode로 보면 0xEB0103와 같이 우리가 읽을 수 없는(?) 데이터로
코드 영역에 들어가 있겠죠.
Q3)
static이 data로 할당되는 것은 C++의 얘기이고
C#은 static도 (managed) heap에 들어갑니다.
C# 기준으로는 그렇게 세세하게 heap/stack/data 등을 생각할 필요가 전혀 없습니다.
Q4)
unsafe 모드로 바꾸고 메모리를 직접 까볼 수 있기는 한데
C# 특성상 메모리를 꽁꽁 숨겨두고 있기에
어지간해서는 C++에서 실습을 하시기 바랍니다.
Q5)
_flag = EMPTY_Flag;
로도 충분합니다.