#include <iostream>
int main()
{
char *dataptr = new char[33];
char datalocal[33];
dataptr[0] = 'a'; dataptr[1] = 0;
datalocal[0] = 'a'; datalocal[1] = 0;
printf("%p %p %c\n", dataptr, &dataptr, dataptr[0]);
printf("%p %p %c\n", datalocal, &datalocal, datalocal[0]);
delete[] dataptr;
}
출력 : 우리가 알 수 있듯이
0xd38050 0x7635bd709448 a
0x7635bd709450 0x7635bd709450 a
동적 포인터 data
포인터 변수 (32 비트 또는 0x7635BD709448
에서 64 비트) 힙, 0xD38050
에 대한 포인터를 포함하는, 정말.
로컬 변수는 주소가 0x7635BD709450
인 33 바이트 길이의 직접 버퍼입니다.
그러나 datalocal
은 char *
값으로도 작동합니다.
저는이 형식적인 C++ 설명이 다소 혼란 스럽습니다.C++ 코드를 작성하는 동안 이것은 매우 자연스럽고 dataptr [0]은 힙 메모리의 첫 번째 요소 (즉, dataptr을 두 번 참조 해제)이지만 어셈블러에서 포인터 변수의 주소 인 dataptr
이라는 참된 특성을 볼 수 있습니다. 따라서 mov eax,[data]
= 덤프 포인터를로드하고 0xD38050
을 사용하여 eax
을로드 한 다음 [eax]
을 사용하여 0xD38050
의 내용을 XMM0에로드 할 수 있습니다.
로컬 변수에는 주소가있는 변수가 없습니다. 심볼 datalocal
은 이미 첫 번째 요소의 주소이므로 movdqu xmm0,[data]
이 작동합니다.
"잘못된"경우에도 여전히 수행 할 수 있습니다 movdqu xmm0,[data]
; 32 비트 변수에서 128 비트를로드하는 것은 CPU의 문제가 아닙니다. 이것은 단순히 32 비트를 넘어서 계속 읽으며 다른 변수/코드에 속한 또 다른 96 비트를 읽습니다. 메모리 경계 근처에서 응용 프로그램의 마지막 메모리 페이지 인 경우 잘못된 액세스로 인해 충돌이 발생합니다.
주석이 몇 번 언급되었습니다. 그것은 유효한 지적입니다. movdqu
을 통해 메모리에 액세스하려면 정렬되어야합니다. C++ 컴파일러 내장 함수를 확인하십시오. 비주얼 스튜디오의 경우이 작업을해야합니다 : 내 C++ 해석에 대해
__declspec(align(16)) char datalocal[33];
char *dataptr = _aligned_malloc(33, 16);
_aligned_free(dataptr);
을 : 어쩌면 나는 처음부터이 잘못되었다.
dataptr
은 dataptr 심볼의 값, 즉 해당 힙 주소입니다. 그런 다음 dataptr[0]
은 할당 된 메모리의 첫 번째 요소에 액세스하여 힙 주소를 역 참조합니다. &dataptr
은 dataptr
값의 주소입니다. 이는 dataptr = nullptr;
과 같은 구문에서도 의미가 있습니다. 여기서 nullptr 값을 dataptr 변수에 저장하고 dataptr 기호 주소를 덮어 쓰지 않습니다. 이 배열 변수로 datalocal[]
와
는 기본적으로 datalocal = 'a';
에 같은 순수한 datalocal
를 액세스하는 것은 의미가 없다, 그래서 당신은 항상 []
인덱스를 제공해야합니다. 그리고 &datalocal
은 그러한 배열의 주소입니다. 순수 datalocal
은 char *
타입을 갖는 배열 등을 사용하는 더 쉬운 포인트 수학을위한 별칭 지름길이지만 순수한 datalocal
이 구문 오류를 던지더라도 여전히 포인터로 &datalocal
을 사용하여 C++ 코드를 작성할 수 있습니다. 요소의 경우 datalocal[..]
),이 코드는 dataptr
논리와 완전히 일치합니다.
결론 : 어셈블리 언어 [data]
이 data
값 (new
에 의해 반환 된 포인터)을로드하고 있기 때문에 처음부터 잘못된 예가있었습니다.
이 내 자신의 설명, 그리고 지금 일부 C++ 전문가 :) ... 와서보기의 공식적인 관점에서 조각을 찢어 것)) 코드와
'data'는 포인터입니다. –
'[data]'가있는 원래의 게시물에서와 같이 포인터가있는 new/delete 대신에 지역 변수'char data [33];'를 직접 사용할 수 있습니까? 지금은 디버그 할 수 없지만, 컴파일 된 소스를 상상할 수있는 것처럼 이것이 작동한다고 생각합니다. 지금 당황하고있는 것은 무엇입니까? char + data와 C++의 차이점은 무엇입니까? C + +의 관점에서 그들은 동등한 것으로 보입니다. 나는 아마 뭔가를 바라보고있을거야. (그리고 두 번째 버전에서'mov eax, data'는'mov eax, [data]'로 컴파일됩니다.) – Ped7g
x86에는 "메모리 간접"주소 지정 모드가 없습니다. 포인터를'xmm0'에로드하고 있습니다. 'xmm0'는 포인터보다 크기 때문에, 포인터가 저장된 곳의 끝 부분에서 메모리의 가비지 바이트를 읽는 것입니다. –