문제
깔끔하게 컴파일되는 일부 코드를 추가했는데 방금 다음 Windows 오류가 발생했습니다.
---------------------------
(MonTel Administrator) 2.12.7: MtAdmin.exe - Application Error
---------------------------
The exception Privileged instruction.
(0xc0000096) occurred in the application at location 0x00486752.
나는 버그 사냥을 하려고 하는데, 내가 한 일이 우연히 이 메시지를 생성한 어리석은 일이 될 것이라고 예상합니다.코드는 오류나 경고 없이 깔끔하게 컴파일됩니다.EXE 파일의 크기는 1,454,132바이트로 늘어났으며 다음 링크를 포함합니다. ODCS.lib
, 그러나 DEBUG가 설정된 Win32 API에 대한 순수 C입니다(Windows 2000의 P4에서 실행).
해결책
질문에 답하기 위해 특권 명령어는 "수퍼바이저"(또는 링-0) 모드에서만 실행될 수 있는 프로세서 연산 코드(어셈블러 명령어)입니다.이러한 유형의 명령어는 Windows 커널에서 I/O 장치 및 보호된 데이터 구조에 액세스하는 데 사용되는 경향이 있습니다.
일반 프로그램은 I/O 장치 등에 대한 직접 액세스를 허용하지 않는 "사용자 모드"(Ring-3)에서 실행됩니다.
다른 사람들이 언급했듯이 원인은 아마도 손상된 스택이거나 엉망인 함수 포인터 호출일 것입니다.
다른 팁
이런 종류의 일은 일반적으로 유효하지 않은 데이터를 가리키는 함수 포인터를 사용할 때 발생합니다.반환 스택을 폐기하는 코드가 있는 경우에도 발생할 수 있습니다.이러한 종류의 버그는 일반적으로 재현하기 어렵기 때문에 추적하는 것이 때로는 매우 까다로울 수 있습니다.
특권 명령어는 링-0에서만 실행이 허용되는 IA-32 명령어입니다(예:커널 모드).사용자 공간에서 이 문제가 발생한다면 정말 오래된 EXE이거나 손상된 바이너리를 갖고 있는 것입니다.
내가 생각할 수 있는 첫 번째 확률은 로컬 배열을 사용하고 있을 수 있으며 함수 선언의 상단 근처에 있다는 것입니다.범위 검사가 미쳐서 반환 주소를 덮어쓰고 커널만 실행할 수 있는 일부 명령을 가리킵니다.
내가 의심했던 것처럼 내가 한 일은 어리석은 일이었습니다.위 메시지의 댓글에 있는 몇 가지 단서 덕분에 이 문제를 두 배나 빨리 해결했다고 생각합니다.특히 앱 초기에 스택 덮어쓰기를 지적한 분들께 감사드립니다.실제로 여기에서 몇 가지 답변이 더 유용하다는 것을 알았습니다. 질문에 대한 답변으로 표시한 게시물이 어디를 봐야 할지에 대한 단서와 대기열을 제공했지만 답변이 가장 잘 요약되어 있다고 생각합니다.
결과적으로 나는 일부 도구 모음 버튼 정보(스택에 있음)를 포함하는 배열의 최대 크기를 초과하는 버튼을 추가했습니다.나는 그것을 잊고 있었다
#define MAX_NUM_TOOBAR_BUTTONS (24)
심지어 존재했다!
오류 위치 0x00486752는 실행 가능한 코드가 일반적으로 존재하기 전에는 정말 작은 것 같습니다.나는 Daniel의 의견에 동의합니다. 그것은 나에게 거친 포인터처럼 보입니다.
나는 이것을 2000년 Visual C++ 6.0에서 보았습니다.
디버그 C++ 라이브러리에는 예외 처리기에서 물리적 I/O 명령에 대한 호출이 있었습니다.내 기억이 정확하다면 DMA 기본 레지스터용이었던 I/O 포트에 상태를 덤프하고 있었는데, Microsoft 직원이 디버거 카드용으로 사용했던 것으로 추정됩니다.
잠재적으로 진단 코드 실행을 유발할 수 있는 일부 오류 조건을 찾으십시오.
나는 디버깅하고, 역추적하고, 디스어셈블리를 읽었습니다.처리하는 동안 예외가 발생했습니다. std::string
, 어쩌면 끝 부분에서 색인을 생성할 수도 있습니다.
지난 15년 동안 제조된 대부분의 프로세서의 CPU에는 매우 강력한 몇 가지 특수 명령이 있습니다.이러한 권한 있는 명령어는 운영 체제 커널 응용 프로그램용으로 유지되며 사용자가 작성한 프로그램에서는 사용할 수 없습니다.
이는 사용자가 작성한 프로그램이 시스템에 가할 수 있는 손상을 제한하고 시스템이 실제로 충돌하는 횟수를 줄입니다.
커널 모드에서 실행될 때 운영 체제는 커널과 사용자 프로그램의 메모리 모두에 무제한으로 액세스할 수 있습니다.
기본 및 한계 레지스터에 대한 로드 명령어는 특권 명령어입니다.