2011-08-03 5 views
10

도입을 수정하는 것입니다 - 길고 지루한 부분

(질문은 끝입니다)타사 코드는 FPU 제어 단어를

내가 얻고 심한 머리를 유지하는 타사 COM 구성 요소를 통해 아파 FPU 제어 워드 변경.

내 개발 환경은 Windows 및 Visual C++ 2008입니다. 일반 FPU 제어 단어는 다양한 조건에서 예외를 throw하지 않아야 함을 지정합니다. 나는 float.h에있는 _CW_DEFAULT 매크로를보고 시작할 때 디버거의 제어 단어를보고 확인했다.

COM 개체를 호출 할 때마다 컨트롤 단어가 반환 될 때마다 수정됩니다. 이것은 방어하기 쉽습니다. 나는 단순히 제어 단어를 재설정하고 모두 좋다. 문제는 COM 구성 요소가 내 이벤트 싱크를 호출하기 시작할 때입니다. 이벤트 호출을 받자 마자 제어 단어를 다시 설정하여 코드를 보호 할 수는 있지만 이벤트 호출에서 복귀하자 마자 아무 것도 할 수 없습니다.

이 COM 구성 요소에 대한 원본이 없지만 저자와 연락 중입니다. 내가 그에게서받은 반응은 "어?"였습니다. 나는 그가 내가 말하는 것에 대해 조금이라도 단서가 없다고 생각한다. 그래서 나는 이것에 대해 무언가를해야한다는 것을 두려워한다. 나는 그의 런타임 (DLL이 심볼 이름으로 가득 차 있기 때문에 델파이 또는 볼랜드 C++이라고 생각한다), 또는 그가 사용하고있는 다른 제 3 자 코드가 문제를 일으키는 것으로 생각한다. 저는 그의 코드가 FPU 제어 단어를 명시 적으로 수정하지 않았다고 생각합니다.

그럼 어떻게해야합니까? 비즈니스 관점에서 볼 때이 타사 구성 요소를 사용해야합니다. 기술적 인 관점에서 볼 때, 나는 그것을 버리고 통신의 프로토콜을 직접 구현할 수 있습니다. 그러나이 프로토콜은 신용 카드 거래를 처리하기 때문에 비용이 많이 듭니다. 우리는 책임을지지 않기를 원합니다.

필자는 컴포넌트 작성자에게 전달할 수있는 Borland 제품의 FPU 설정에 관한 유용한 정보 나 해킹이 절실히 필요합니다. 내가 할 수있는 일

질문

있습니까? 나는 구성 요소 작성자가 그것을 고치기 위해 무엇을 가지고 있다고 생각하지 않는다. (오히려 우둔한 대답으로 판단함으로써).

나는 처리기에서 제어 단어를 재설정하고 Windows에서 계속 실행하도록 내 자신의 예외 처리기를 설치한다는 생각에 놀랐다. SetUnhandledExceptionFilter()과 함께 처리기를 설치하려고했지만 어떤 이유로 든 예외가 포착되지 않았습니다.

  1. 예외가 발생하지 않는 이유는 무엇입니까?
  2. FPU 예외를 포착하고 FPU 제어 단어를 재설정하고 아무 일도 일어나지 않은 상태로 실행을 계속하면 모든 베팅이 해제됩니까?

업데이트

내가 그들의 제안을 모든 사람에게 감사의 말씀을 전합니다. 저는 저뿐만 아니라 그의 코드의 다른 많은 고객들을 위해 인생을 편하게하기 위해 그가 할 수있는 것에 대한 저자 지침을 보냈습니다. 필자는 그가 FPU 제어 워드를 DllMain(DLL_PROCESS_ATTACH)에 샘플링하고 나중에 제어 워드를 저장해야하므로 FPU CW를 내 이벤트 핸들러를 호출하기 전에 리셋 할 수 있고 내 호출에서 복귀 할 수 있다고 제안했다.

지금은 관심있는 사람이라면 해킹을 시도합니다. hack-around는 잠재적으로 나쁜 것입니다. 왜냐하면 나는 그의 코드 코드로 무엇을할지 모르기 때문입니다. 이전에 코드에서 부동 소수점 숫자를 사용하지 않고 확인을 받았으므로 FPU 예외를 사용하는 일부 제 3 자 코드는 제외하고이 코드가 안전해야합니다.

내 응용 프로그램에 적용한 두 개의 수정 :

  1. 메시지 펌프 바이 패스 코너 케이스를 잡으려고 창 후크 (WH_CALLWNDPROC)를 설치 내 메시지 펌프
  2. 랩은

두 경우 모두 FPU CW가 변경되었는지 확인합니다. 있을 경우 _CW_DEFAULT으로 재설정합니다.

+2

http://www.virtualdub.org/blog/pivot/entry.php?id=53; "위험한"코드 경로 이후에 FPU 제어 세계를 복원하는 코드가 추가되었지만 "Borland 런타임 라이브러리의이 동작을 비활성화하고이 문제를 피하는 것이 가능합니다" –

+0

@matteo , 링크를 가져 주셔서 감사합니다. 흥미로운 읽기! 나는 그것을 저자에게 전달할 것이다. –

+0

그건 그렇고, 그 게시물에 언급 된 그 행동을 해제하는 방법은 사실 그의 대답에 @ 데이비드에 의해 설명 Set8087CW 기능을 사용하는 것 같아요. –

답변

6

엠바 카데로 제품에 구성 요소가 기록되어 있다는 진단은 사실 일 가능성이 큽니다. Delphi의 런타임 라이브러리는 실제로 C++ Builder와 마찬가지로 부동 소수점 예외를 사용할 수 있습니다.

Embarcaderos 도구에 대한 좋은 점 중 하나는 부동 소수점 오류가 언어 예외로 변환되어 숫자 코딩을 훨씬 쉽게 할 수 있다는 것입니다. 그것은 당신에게 조금 위로가 될 것입니다!

이 전체 영역은 거대한 PITA입니다. FP 통제 단어와 관련하여 어떠한 규칙도 없습니다. 그것은 총 무료입니다.

처리되지 않은 예외를 잡는 것이 MS C++ 런타임이 아마도 이미 이러한 예외를 잡기 때문에 수행되지 않을 것이라고 나는 믿지 않지만 그 영역의 전문가는 아니며 잘못되었을 수 있습니다.

유일한 현실적인 해결책은 실행이 코드에 도착할 때마다 원하는대로 FPU를 설정하고 실행이 코드를 떠날 때 FPU를 복원하는 것입니다. COM 이벤트 싱크에 대해 충분히 알지 못하기 때문에 왜 이러한 문제가 발생했는지 이해할 수 없습니다.

내 제품에 Delphi에서 구현 된 DLL이 포함되어 있으며 역의 문제가 있습니다. 대부분 호출하는 클라이언트는 예외를 비활성화하는 FPU 제어 워드를 가지고 있습니다. 우리가 채택한 전략은 진입시 8087CW를 기억하고 코드를 실행하기 전에 표준 Delphi CW로 설정 한 다음 종료 지점에서 복원하는 것입니다. 콜백을하기 전에 발신자의 8087CW를 복원하여 콜백도 처리합니다. 이것은 COM 객체가 아닌 일반 DLL이므로 조금 더 간단합니다.

COM 공급자가 코드를 수정하려고 시도 할 경우 Set8087CW() 함수를 호출해야합니다.

그러나 게임에 규칙이 없으므로 COM 객체 공급 업체가 코드 변경을 거부하고 책임을 다시지지한다고 정당화됩니다.

죄송합니다. 이것이 100 % 결론적 인 답변이 아니지만 의견에 대한 모든 의견을 얻을 수는 없습니다.

+0

정보를 제공해 주셔서 감사합니다! 나는 다른 사람이 나를 도와 줄 수 있기를 바란다. 나는 그를 위해 수익을 얻고 있기 때문이다. 그가 새로운 인터페이스를 구현한다면, IFPUControlWordPolicy를 통해 내가 선호하는 CW를 등록 할 수 있다고 생각하면 CW가 내가 원했던대로 설정되었는지 확인하고, 원하는 CW로 복원 할 수 있습니다. 걸려 오는 전화 등. FPU CW를 수정하는 "그의 장면"뒤에 실행되는 런타임 코드가있을 수 있습니다. 그는 그가 FPU CW에 아무 것도하지 않는다고 주장하며, 어떻게 든 FPU CW가 수정됩니다 ... –

+0

... 이벤트 싱크에서 돌아올 때 CW가 수정 된 것 같습니다. 이벤트를 비동기 적으로 생성하고있는 것으로 의심됩니다 (즉, 구성 요소에 대한 호출 결과로 생성되지 않음). 그러면 CW가 수정됩니다. 이 시나리오에서는 내 코드가 해당 시점의 호출 스택에 없으므로이 점을 방어 할 수는 없습니다. :/ –

+0

엠마 런타임은 CW를 가장 명확하게 설정합니다. 그는 그것을 명백하게하지 않을 것입니다. 그의 코드는 FP 예외에 의존 할 수 있습니다. –

6

FP 제어 워드는 스레드마다 있지만 새 스레드가 만들어지면 dllmain 함수가 호출되기 때문에 새로운 프로세스로 전환하는 것을 피할 수 있다고 생각하지 않습니다.

COM을 실행하고 원하는 프로세스 간 통신 방법으로 프로세스와 채팅하기 위해 새 프로세스를 시작하는 것이 좋습니다.윈도우 메시지, out-of-proc COM, 명명 된 파이프, 소켓 등). 이 방법으로 COM 서버는 호스트 프로세스를 중단시키지 않고 모든 종류의 손상 (자체 충돌 포함)을 수행 할 수 있습니다.

또 다른 아이디어는 해당 DLL의 DllMain에서 FPU를 재설정하고 문제가 발생한 DLL 바로 뒤에로드하는 것이 유일한 목적입니다. Windows는 COM 서버가 생성 한 스레드를 포함하여 새 스레드가 생성 될 때 DllMain을 호출하기 위해로드 순서를 사용하고 있습니다. Windows의 내부 동작에 따라 달라집니다. 또한 COM 서버는 실제로 fp 예외를 사용할 수 있기 때문에 실제로 fp 예외에 의존 할 수 있습니다. FP 예외를 사용하지 않으면 COM 서버가 예기치 않게 작동 할 수 있습니다.

+0

CW는 델파이 코드가 실행될 때마다 반복적으로 리셋되어야합니다. –