어떻게 할 수 있습니까? 함수 외부에서 로컬 변수의 메모리에 액세스 할 수 없습니까?
호텔 방을 임대하십시오. 침대 옆 테이블의 상단 서랍에 책을 넣고 자러갑니다. 다음날 아침에 체크 아웃하지만 열쇠를 돌려주는 것을 잊어 버렸습니다. 열쇠를 훔쳐!
일주일 후, 당신은 호텔로 돌아와 체크인하지 않고 열쇠를 훔친 오래된 방으로 몰래 들어가서 서랍을 봅니다. 당신의 책은 여전히 있습니다. 놀라운!
어떻게 그렇게 될수 있니? 방을 임대하지 않은 경우 호텔 방 서랍의 내용에 액세스 할 수 없습니까?
분명히,이 시나리오는 현실 세계에서 아무 문제없이 일어날 수 있습니다. 더 이상 방에있을 권한이 없을 때 책이 사라지는 신비한 힘은 없습니다. 도난당한 열쇠로 방에 들어 가지 못하게하는 신비한 힘도 없습니다.
호텔 관리자는 책을 제거 할 필요 가 없습니다 . 당신이 물건을 남겨두면 그들은 당신을 위해 그것을 파쇄 할 것이라고 말했다 당신은 그들과 계약을하지 않았다. 열쇠를 훔쳐 열쇠를 가지고 불법적으로 방에 다시 들어간 경우에는 호텔 경비원이 당신을 몰래 잡을 필요 가 없습니다 . "내가 몰래 들어 오려고하면 나중에 방을 막아야합니다. " 오히려, 당신은 계약 "나중에 내 방으로 다시 몰래하지 않겠다고 약속"고 말했다 그들과 계약을 체결 당신이 파산을 .
이 상황에서는 어떤 일이든 일어날 수 있습니다 . 책은 거기있을 수 있습니다. 운이 좋았습니다. 다른 사람의 책이있을 수 있으며 호텔의 화로에있을 수도 있습니다. 당신이 들어 와서 책을 여러 조각으로 찢어 버릴 수 있습니다. 호텔에서 테이블을 제거하고 완전히 예약하여 옷장으로 교체했을 수 있습니다. 호텔 전체가 찢겨지고 축구 경기장으로 교체 될 수 있으며, 몰래 숨을 쉴 때 폭발로 사망 할 수 있습니다.
당신은 무슨 일이 일어날 지 모른다. 당신이 호텔에서 체크 아웃 불법 나중에 사용하기 위해 키를 훔쳐 때, 당신 때문에 예측, 안전한 세상에서 살 권리 포기 는 시스템의 규칙을 깰 선택합니다.
C ++는 안전한 언어가 아닙니다 . 유쾌하게 시스템의 규칙을 어길 수 있습니다. 만약 당신이 방으로 돌아가는 것처럼 불법적이고 어리석은 짓을하려고한다면 더 이상 없을 수도있는 책상을 통해 들어갈 수 없으며 C ++은 당신을 막을 수 없습니다. C ++보다 안전한 언어는 예를 들어 키를 훨씬 엄격하게 제어하여 전력을 제한함으로써이 문제를 해결합니다.
최신 정보
신의 선하심,이 대답은 많은 주목을 받고 있습니다. (왜 그런지 잘 모르겠다. 나는 그것이 단지 "재미있는"작은 비유라고 생각했다.
나는 약간의 기술적 인 생각으로 이것을 조금 업데이트하는 것이 독창적이라고 생각했다.
컴파일러는 해당 프로그램에 의해 조작 된 데이터의 저장을 관리하는 코드를 생성하는 사업에 있습니다. 메모리를 관리하기 위해 코드를 생성하는 방법에는 여러 가지가 있지만 시간이 지남에 따라 두 가지 기본 기술이 확립되었습니다.
첫 번째는 스토리지에있는 각 바이트의 "수명"즉, 일부 프로그램 변수와 유효하게 연관된 기간을 미리 쉽게 예측할 수없는 일종의 "긴 수명"스토리지 영역을 갖는 것입니다. 시간. 컴파일러는 필요할 때 스토리지를 동적으로 할당하고 더 이상 필요하지 않은 경우이를 회수하는 방법을 알고있는 "힙 관리자"에 대한 호출을 생성합니다.
두 번째 방법은 각 바이트의 수명이 잘 알려진 "짧은 수명"저장 영역을 갖는 것입니다. 여기서 수명은 "중첩"패턴을 따릅니다. 이 수명이 가장 짧은 변수는 다른 수명이 짧은 변수보다 먼저 할당되고 마지막에 해제됩니다. 수명이 짧은 변수는 수명이 가장 긴 변수 다음에 할당되고 변수가 해제되기 전에 해제됩니다. 수명이 짧은 변수의 수명은 수명이 긴 변수의 수명 내에 "중첩"됩니다.
지역 변수는 후자의 패턴을 따릅니다. 메소드가 입력되면 로컬 변수가 활성화됩니다. 해당 메소드가 다른 메소드를 호출하면 새 메소드의 로컬 변수가 활성화됩니다. 첫 번째 방법의 지역 변수가 죽기 전에 죽을 것입니다. 지역 변수와 관련된 스토리지 수명의 시작과 끝의 상대적 순서는 미리 해결할 수 있습니다.
이러한 이유로 로컬 변수는 일반적으로 "스택"데이터 구조의 저장소로 생성됩니다. 스택에는 첫 번째로 푸시 된 속성이 마지막으로 생성 된 속성이 있기 때문입니다.
호텔이 순차적으로 객실을 임대하기로 결정한 것처럼 객실 번호가 높은 사람이 모두 체크 아웃 할 때까지 체크 아웃 할 수 없습니다.
스택에 대해 생각해 봅시다. 많은 운영 체제에서 스레드 당 하나의 스택이 생성되고 스택은 특정 고정 크기로 할당됩니다. 메소드를 호출하면, 내용물이 스택으로 푸시됩니다. 그런 다음 원래 포스터에서와 같이 메소드에서 스택으로 포인터를 다시 전달하면 완전히 유효한 백만 바이트 메모리 블록의 중간에 대한 포인터 일뿐입니다. 우리의 비유로, 당신은 호텔을 체크 아웃합니다; 당신이 할 때, 당신은 방금 가장 높은 자리를 체크 아웃했습니다. 다른 사람이 체크인 한 후 아무도 체크인하지 않고 불법적으로 방으로 돌아 가면 모든 물건 이이 특정 호텔에 여전히 있어야 합니다.
스택은 실제로 저렴하고 쉬우므로 임시 저장소에 스택을 사용합니다. C ++ 구현은 로컬 저장을 위해 스택을 사용하지 않아도됩니다. 힙을 사용할 수 있습니다. 그것은 프로그램을 느리게 만들 것이기 때문에 그렇지 않습니다.
C ++의 구현은 스택에 남겨둔 쓰레기를 건드리지 않고 나중에 불법으로 다시 올릴 수 있도록 요구하지 않습니다. 방금 비운 "방"의 모든 것을 0으로 되 돌리는 코드를 컴파일러가 생성하는 것은 완전히 합법적입니다. 다시 비싸지 않기 때문에 비용이 많이 듭니다.
스택이 논리적으로 축소 될 때 유효했던 주소가 여전히 메모리에 매핑되도록 C ++을 구현할 필요는 없습니다. 구현은 운영 체제에 "지금 우리는이 스택 페이지를 사용하여 완료되었습니다. 달리 말할 때까지 누군가가 이전에 유효한 스택 페이지를 건 드리면 프로세스를 파괴하는 예외를 발행합니다"라고 말할 수 있습니다. 다시, 구현은 느리고 불필요하기 때문에 실제로는 그렇게하지 않습니다.
대신 구현을 통해 실수를 저지르고 벗어날 수 있습니다. 대부분의 경우 언젠가 진정으로 끔찍한 일이 잘못되고 과정이 폭발합니다.
문제가 있습니다. 많은 규칙이 있으며 실수로 규칙을 어기는 것은 매우 쉽습니다. 나는 확실히 여러 번 있습니다. 더 나쁜 것은, 손상이 발생한 후 메모리가 수십억 나노초로 손상된 것으로 밝혀 졌을 때, 메모리를 누가 엉망으로 만들지 알아내는 것이 매우 어려운 경우에만 종종 문제가 발생한다는 것입니다.
더 안전한 메모리 언어는 전원을 제한하여이 문제를 해결합니다. "정상"C #에서는 단순히 로컬 주소를 가져 와서 반환하거나 나중에 저장하는 방법이 없습니다. 당신은 지역의 주소를 취할 수 있지만, 언어는 지역 끝이 끝난 후에는 언어를 사용할 수 없도록 영리하게 설계되었습니다. 로컬 주소를 가져 와서 다시 전달하려면 컴파일러를 특수한 "안전하지 않은"모드로 설정 하고 프로그램에 "안전하지 않은"이라는 단어를 넣어야 할 것입니다. 규칙을 어길 수있는 위험한 것.
더 읽을 거리 :
address of local variable ‘a’ returned
. valgrind showsInvalid write of size 4 [...] Address 0xbefd7114 is just below the stack ptr