2010-01-20 3 views
8

일부 메모리 관리 트릭을 수행하기 위해 operator new()operator delete()을 (모든 변형과 함께) 교체하고 싶습니다. 내 응용 프로그램의 모든 코드에서 사용자 지정 연산자 (타사 DLL뿐만 아니라 자체 DLL의 코드 포함)를 사용하고 싶습니다. 링커가 링크 할 때 첫 번째 정의를 선택한다는 것을 읽었습니다 (예 : operator new()이 포함 된 라이브러리가 먼저 링크되면 CRT와 링크가 "박"됩니다). 이것이 일어날 것을 보장 할 수있는 방법이 있습니까? 이 규칙은 실제로 다중 정의 기호이므로 (예 : void* operator new(size_t size)은 전역 이름 공간에 두 개의 정의가 있음)이 규칙이 무엇입니까?어디에서나 전역 "연산자 new()"를 대체 할 수 있습니까?

CRT와 정적으로 연결된 타사 DLL은 어떻습니까? CRT와 동적으로 연결되어 있다고하더라도, 내가 그들과 연결할 수있는 방법이 있습니까 operator new()?

+6

위험이 따르고 있습니다. 이 작업을 수행 하시겠습니까 (y/N)? > –

+1

DLL은 바이너리이므로, DLL은 이미 컴파일되고 링크되어 있습니다. – KingRadical

+2

충분히 좋습니다. 다음 번 StackOverflow 질문이 "매우 중요한 프로덕션 시스템에서 데이터를 복구하는 방법"이라면 나는 기분이 좋을 것입니다. ;) –

답변

7

C++ 표준을 사용하면 전역 연산자 new 및 delete (및 배열 변형)을 작성할 수 있습니다. 링커는 제대로 작동해야하지만, 구현자가 어떻게 할 것인가 (예 : 약한 외부 객체는 이미 존재하지 않는 경우에만 무언가를 제공하는 데 도움이 될 수 있습니다).

DLL에 관한 한 까다로울 것입니다. 정적으로 링크 된 DLL은 많은 추가 작업없이 코드를 분명히 사용하지 않을 것입니다. 정적 연결이란 이미 DLL에 복사 된 라이브러리 코드 사본을 가지고 있으며 DLL에있는 모든 코드는 이미 인코딩 된 해당 코드의 주소를 가지고 있습니다. 이 문제를 해결하려면 new에 대한 코드가 DLL에있는 곳을 파악하고 DLL을 호출하여 DLL을 호출하도록 모든 코드를 동적으로 패치해야합니다.

DLL이 동적으로 표준 라이브러리에 연결되면 가져 오기 테이블이 여전히 DLL의 이름을 인코딩하고 필요한 DLL을 제공합니다. DLL은 Microsoft의 Detours library과 같이 사용할 수 있지만 DLL은 표준 라이브러리를 정적으로 연결하는 것보다 확실히 쉽습니다.

3

편집 : 질문을 다시 읽은 후, 귀하의 강조가 타사 구성 요소에 있음을 알고 있습니다. 그래서 그 경우 대답은 '아니오'입니다. 너무 많은 변수가 관련되어 있습니다.


(코드를 "new"로 바꾸는 것을 참고하십시오) 짧은 대답은 '예'입니다. 이는 자체 메모리 관리를 수행하는 시스템에서 공통적 인 트릭입니다. 당신이 짐작 했겠지만, 옳은 것은 매우 까다로운 일이며 조심하지 않으면 얼굴에 쉽게 파열 될 수 있습니다. 그러나 확실히 그럴듯하고 많은 소프트웨어에서 사용됩니다. (예를 들어 Doom 3 SDK에서이 작업을 수행하는 일부 코드를 읽은 것을 기억합니다.)

타사 DLL에서 새 코드와 삭제 코드를 대체하는 경우에는 적어도 안전하지는 않습니다. 하나는 새로운 것을 사용하고 삭제한다는 것을 어떻게 알 수 있습니까? 말할 것도없이이 기술의 자체 변종을 수행하고 적절하게 기능하기위한 일부 부작용에 의존 할 수 있습니다. 그리고 지금 작동 시키더라도, 그 컴포넌트의 미래 버전이 그것을 깨뜨리지 않을 것이라고 어떻게 알 수 있습니까? 자신이 원하는 모든 것을 마음대로 골라 낼 수는 있지만, 사용자와 사용자의 건강을 위해 다른 바이너리의 메모리를 미세하게 관리하지 마십시오.

관련 문제