2015-02-03 5 views
0

배경 :64 비트 포인터는 64 비트 컴퓨터에서만 하위 32 비트를 사용합니까?

나는 다음과 같은 간단한 코드를 가지고 : get_result()은 (여기에 64 비트 시스템에서 64 핀터이어야 함)에 대한 포인터를 반환 뭔가

Object * copied_object = get_result(original_object); 

. get_result() 함수를 선언하지 않으면, gcc는 기본적으로 함수의 int를 반환 할 것이므로 result에는 잘린 포인터 (왼쪽 32 비트 만)가 포함될 것입니다.이 문제로 인해 sig11 오류가 발생했습니다.

그러나 내 프로그램을 실행하면 내 오류가 비결정적으로 나타나는 것 같습니다. 처음에는이 논리를 루프에 넣었고 명령 줄에서 신호를 보낼 때마다 위 코드가 실행될 것이고, 그래서 sig11이 내 프로그램을 크래시하지 않도록 시그널 핸들러를 가지고있다.) 디버깅 후 다음과 같은 시간에 함수에서 반환 된 포인터는 하위 32 비트 (심지어 original_object 같은 포인터도 아래 32 비트 사용) 만 사용한다는 것을 알게되었습니다. 따라서 잘라내 기가 아무런 문제를 일으키지 않았습니다.

질문 :

내 질문은 우리가 64 기계에 대한 포인터의 하위 32 비트를 사용합니까 어떤 조건입니까? 포인터를 할당하는 패턴은 무엇입니까?

도움이되었거나 참고 문헌을 매우 환영합니다.

+0

나는 당신이 길을 나갔다 (올바른 프로 시저 선언을 생략함으로써) 포인터가 잘리는 이유를 알지 못한다. 그것의 좋은 것은 올 수 없다. – slipperyseal

+0

감사합니다. 물론 코드에서 포인터 잘림을 남기지 않을 것입니다. 나는 매번 동일한 오류가 발생하지 않는 이유를 여기에서 이해하려고 노력하고 있지만, 단지 처음으로 - 안정적으로, 매회. – Lonely

+0

한 가지 이유 : http://en.wikipedia.org/wiki/Address_space_layout_randomization – hyde

답변

1

운영 체제 및 프로그램 연결 방법에 따라 다릅니다. 그러나 사용자 모드 프로그램은 거의 항상 가상 메모리의 아래쪽 절반에서 실행됩니다. 반면에 커널은 주소 공간의 상위 절반에 매핑됩니다.

또한 대부분의 프로그램은 기본 주소가 0x400000이므로 링크가 너무 크지 않으면 대부분의 포인터가 32 비트 포인터 내에 있습니다. 리눅스의 많은 공유 라이브러리는 결국 매핑이 높아집니다.

+1

하지만 [ASLR] (http : //en.wikipedia.org/wiki/Address_space_layout_randomization), 프로그램에서 사용 된 주소가 반드시 하위 4GB에 맞지는 않습니다 –

0

에 따라 다릅니다. 부호없는 32 비트 정수를 사용하여 메모리의 첫 번째 4 GiB를 올바르게 지정할 수 있습니다. 그러나 함수에 프로토 타입이 정의되어 있지 않으면 호출자는 부호가 인 정수를 반환 할 것으로 예상합니다.이 정수는 메모리가 부족한 2 GiB와 높은 메모리 2 GiB를 처리 할 수 ​​있습니다 (2의 보수가 signed int라고 가정).
C 언어는 유효한 개체를 지나서 주소를 계산할 수 있어야한다는 점을 제외하고는 주소에 대해 아무 것도 지정하지 않으므로 특정 개체를 처리 할 수 ​​있는지 여부는 더욱 복잡합니다. 물론 포인터를 자르는 경우에는 작동하지 않습니다.
현대 OS/로더가 의도적으로 주소 공간을 무작위로 선택하여 보안 취약성에 대처하는 경우 64 비트 모드로 실행하려면 프로그램을 64 비트로 정리해야합니다. 불가능할 경우 32 비트 모드 (해당되는 경우)를 고수하십시오.

관련 문제