|
축구 님이 쓰신 글 :
: 예를들어 구조체를 쓸때
:
: stTest란 구조체가있을때
:
: 선언을 stTest test; 이렇게 하던지
:
: stTest *test; 이렇게도 하고,
:
: stTest *test = new stTest; 이런 식으로도 하는데요.
:
: 이거에 차이점이 무엇인가요?? 어떤경우에 어떤 선언을 써야 하는건지 설명좀 부탁드려요
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
네, 안녕하세요?
초보 시절엔 궁금한 내용이긴하지요....
약간은 메모리 구조를 이해해야 하는데....
일단, 사용하는 방법에 따라 메모리 영역을 다르게 생성합니다.
우선 대략 실제 런타임 메모리 영역이
코드영역, 데이터영역, 힙영역, 스택영역으로 생깁니다.
메모리 모델에 따라, 컴파일러의 종류에 따라 alias 는 좀 달라지긴하는데...
1) stTest test; 이렇게 하시면, 선언하는 위치에 따라 조금 다른데, 지역 블럭에 선언되면 스택 영역에 생성이 되고,
아니면, 데이터 영역에 생성이 될 겁니다.
이 경우 멤버변수나 매쏘드를 접근할 경우는 test.member; test.method(); 로 접근을 합니다.
변수의 생명 주기는 스택일 경우, 매쏘드 리턴을 하면 스택에서 제거될 것이고, 데이터 영역은 상황에따라, 프로그램이
종료될때까지 살아남을 것입니다.
2) stTest *test = new stTest;
이 표현은 힙에 동적 생성이 되는 건데, 반드시 프로그래머가 delete test, test=0; 이런식으로 제거를 해 줘야 합니다.
물론 이건 구조체 혹은 객체 포인터가 되기 때문에 test가 정상적으로 메모리 할당을 받아야 하고, 널이 아닐 경우
test->member; test->method(); 의 표현을 사용해야 합니다.
3) 마지막으로는 1), 2)를 결합한 건데, stTest test; 이렇게하고나서, stTest *p = &test;
이렇게사용을 합니다. 상황에 따라 단일 포인터를 이용해 서로 다른 객체나 구조체를 접근할 수 있기때문에 사용합니다.
또는 함수의 인자로 넘겨줄때, 객체를 직접 넘겨주면 크기가 커지는데, 포인터로 넘기면, 기본적으로 32비트에선 4바이트만
인자로 넘어갑니다. 특히 객체의 어레이를 넘길땐 차이가 아주 많이 날겁니다. 물론 이경우 주의할 점은 지역블럭의 변수를
선언하고 포인터를 가지고 지역블럭을 넘나들면 상황에따라 아주 위험합니다. 초/중급 개발자들도 매우 실수를 많이 하던데,
스택변수는 리턴하면 없어진다는 점을 반드시 명심해야 합니다.
중요한건 2) 경우는 개발자가 직접 메모리 해제를 해 줘야 한다는 건데요. 이 변수나 객체의 라이프싸이클 관리를 제대로하지 못하면
메모리 누수가 발생하게됩니다. 물론 이 경우도 프로그램이 종료되면 힙은 모두 제거되지만, 서버같은 경우라면, 런타임시 메모리 누수
로 인해 서비스가 멈추게 될 겁니다.
따라서 동적 메모리 관리는 C/C++에서 고수가 되어도 쉬운 상황은 아닙니다. 특히, delete 되고 난 후에도 포인터를 사용할 려고 하는
상황도 생깁니다. 이런 경우는 dangling 포인터라고 하고, 자바 같은 경우는 null 포인터 예외가 발생되는 것입니다.
이 부분은 자바에서 가비지컬렉터라는 것을 사용하여, 개발자가 delete를 해 주지 않아도 되도록 된 것입니다.
때문에 상대적으로 자바는 서버에 유리한 점이 많습니다.
도움이 되었는지 궁금하군요. 짧은 지식으로 너무 장황하게 설명한 것 같네요.
|