힙에 객체가 생성되는 것을 방지하는 방법은 무엇입니까?
문제
플랫폼 독립적인 C++ 코드에서 객체가 힙에 생성되는 것을 방지하는 방법을 아는 사람이 있습니까?즉, "Foo" 클래스의 경우 사용자가 다음을 수행하는 것을 방지하고 싶습니다.
Foo *ptr = new Foo;
다음 작업만 허용합니다.
Foo myfooObject;
누구든지 어떤 아이디어가 있습니까?
건배,
해결책
닉의 대답 좋은 출발점이지만 실제로 과부하가 필요하므로 불완전합니다.
private:
void* operator new(size_t); // standard new
void* operator new(size_t, void*); // placement new
void* operator new[](size_t); // array new
void* operator new[](size_t, void*); // placement array new
(좋은 코딩 방법에서는 delete 및 delete[] 연산자도 오버로드해야 한다고 제안합니다. 그렇게 하고 싶지만 호출되지 않으므로 그렇지 않습니다. 정말 필요한.)
파울두 Foo에서 상속된 상태에서는 유지되지만 Foo에서 집계된 상태에서는 유지되지 않는다는 것도 맞습니다.이를 방지하기 위해 몇 가지 템플릿 메타 프로그래밍 마법을 사용할 수 있지만 "사악한 사용자"의 영향을 받지 않으므로 복잡해질 가치가 없을 것입니다.어떻게 사용해야 하는지에 대한 문서화와 올바르게 사용되었는지 확인하기 위한 코드 검토가 유일한 100% 방법입니다.
다른 팁
Foo에 대해 new를 오버로드하여 비공개로 만들 수 있습니다.이것은 컴파일러가 신음한다는 것을 의미합니다 ...Foo 내에서 힙에 Foo 인스턴스를 생성하지 않는 한.이 경우를 포착하려면 Foo의 새 메서드를 작성하지 않으면 링커가 정의되지 않은 기호에 대해 불평하게 됩니다.
class Foo {
private:
void* operator new(size_t size);
};
추신.예, 쉽게 우회할 수 있다는 것을 알고 있습니다.정말 추천하는 것이 아닙니다. 제 생각에는 나쁜 생각인 것 같습니다. 저는 단지 질문에 대답했을 뿐입니다!;-)
안정적이고 이식 가능한 방식으로 수행하는 방법을 모르겠습니다.하지만..
객체가 스택에 있으면 생성자 내에서 'this' 값이 항상 스택 포인터에 가깝다고 주장할 수 있습니다.이 경우 개체가 스택에 있을 가능성이 높습니다.
모든 플랫폼이 동일한 방향으로 스택을 구현하는 것은 아니라고 생각하므로 앱이 스택이 어느 방향으로 성장하는지 확인하기 시작할 때 일회성 테스트를 수행하는 것이 좋습니다.아니면 퍼지를 해보세요:
FooClass::FooClass() {
char dummy;
ptrdiff_t displacement = &dummy - reinterpret_cast<char*>(this);
if (displacement > 10000 || displacement < -10000) {
throw "Not on the stack - maybe..";
}
}
@건강 상태
Foo에서 파생되거나 Foo를 집계하는 클래스를 생성하면 이 문제를 피할 수 있습니다.나는 내가 제안한 것이 (강력하지는 않지만) 파생 클래스와 집계 클래스에 여전히 작동할 것이라고 생각합니다.
예:
struct MyStruct {
Foo m_foo;
};
MyStruct* p = new MyStruct();
여기에서는 Foo의 숨겨진 new 연산자를 우회하여 힙에 'Foo' 인스턴스를 만들었습니다.
디버그 헤더는 연산자의 새 서명을 재정의할 수 있으므로 ...을 사용하는 것이 가장 좋습니다.완전한 해결책으로서의 서명:
private:
void* operator new(size_t, ...) = delete;
void* operator new[](size_t, ...) = delete;
Foo 클래스 내에 "operator new"라는 함수를 선언하면 일반적인 형태의 new에 대한 액세스를 차단할 수 있습니다.
이것이 당신이 원하는 행동입니까?
이를 인터페이스로 선언하고 자신의 코드에서 구현 클래스를 보다 직접적으로 제어할 수 있습니다.
이는 생성자를 비공개로 만들고 정적 멤버를 제공하여 스택에 객체를 생성함으로써 방지할 수 있습니다.
Class Foo
{
private:
Foo();
Foo(Foo& );
public:
static Foo GenerateInstance() {
Foo a ; return a;
}
}
이렇게 하면 항상 스택에 객체가 생성됩니다.
이것이 컴파일 타임 기회를 제공하는지 확실하지 않지만 클래스에 대한 'new' 연산자 오버로드를 살펴보셨습니까?