문제

다음 코드가 있다고 가정합니다.

void* my_alloc (size_t size)
{
   return new char [size];
}

void my_free (void* ptr)
{
   delete [] ptr;
}

이거 안전한가요?아니면 꼭 ptr 캐스팅되다 char* 삭제 전?

도움이 되었습니까?

해결책

"안전"에 달려 있습니다. 일반적으로 정보가 할당 자체에 대한 포인터와 함께 저장되므로 거래가이를 올바른 위치로 반환 할 수 있기 때문에 작동합니다. 이런 의미에서는 할당자가 내부 경계 태그를 사용하는 한 "안전"입니다. (많은 일입니다.)

그러나 다른 답변에서 언급했듯이, 빈 공간 포인터를 삭제하는 것은 소멸자를 호출하지 않으므로 문제가 될 수 있습니다. 그런 의미에서 그것은 "안전"이 아닙니다.

당신이하고있는 방식으로하고있는 일을할만한 이유는 없습니다. 자신의 거래 기능을 작성하려면 기능 템플릿을 사용하여 올바른 유형으로 기능을 생성 할 수 있습니다. 그렇게해야 할 좋은 이유는 풀 할당자를 생성하는 것이며, 이는 특정 유형에 대해 매우 효율적일 수 있습니다.

다른 답변에서 언급했듯이 이것은입니다 정의되지 않은 행동 C ++에서. 일반적으로 주제 자체가 복잡하고 상충되는 의견으로 가득 차 있지만 정의되지 않은 행동을 피하는 것이 좋습니다.

다른 팁

공극 포인터를 통해 삭제하는 것은 C ++ 표준에 의해 정의되지 않음 - 섹션 5.3.5/3 참조 :

첫 번째 대안 (Delete Object)에서, 피연산자의 정적 유형이 동적 유형과 다르면, 정적 유형은 피연산자의 동적 유형의 기본 클래스가되어야하며 정적 유형은 가상 파괴자가 있거나 동작이 정의되지 않아야합니다. . 두 번째 대안 (삭제)에서 삭제 될 객체의 동적 유형이 정적 유형과 다르면 동작이 정의되지 않습니다.

그리고 각주 :

이것은 유형 void의 객체가 없기 때문에 유형 void의 포인터를 사용하여 객체를 삭제할 수 없음을 의미합니다.

.

좋은 생각이 아니며 C ++에서 할 일이 아닙니다. 당신은 이유없이 유형 정보를 잃고 있습니다.

비 원시 유형에 대해 호출 할 때 삭제하는 배열의 객체에서 소멸자가 호출되지 않습니다.

대신 새/삭제를 무시해야합니다.

void*를 삭제하면 우연히 메모리가 올바르게 자유롭게 해제 될 수 있지만 결과가 정의되지 않기 때문에 잘못된 것입니다.

어떤 이유로 나에게 알려지지 않은 경우 포인터를 무효로 보관해야한다면* 무료로 사용해야합니다. Malloc과 무료를 사용해야합니다.

공극 포인터를 삭제하는 것은 실제로 가리키는 값에 따라 소멸자가 호출되지 않기 때문에 위험합니다. 이로 인해 응용 프로그램에서 메모리 / 리소스 누출이 발생할 수 있습니다.

질문은 의미가 없습니다. 당신의 혼란은 사람들이 자주 사용하는 조잡한 언어 때문일 수 있습니다. delete:

너는 사용한다 delete 파괴하려면 물체 동적으로 할당되었습니다. 그렇게, 당신은 a를 형성합니다 표현식을 삭제하십시오 a 그 대상에 대한 포인터. 당신은 결코 "포인터를 삭제"하지 않습니다. 당신이 실제로하는 일은 "주소로 식별되는 객체를 삭제하십시오"입니다.

이제 우리는 왜 질문이 의미가 없는지 알 수 있습니다. 공허 포인터는 "객체의 주소"가 아닙니다. 의미론이없는 주소 일뿐입니다. 그것 5월 실제 객체의 주소에서 나왔지만 그 정보는 유형 원래 포인터의. 객체 포인터를 복원하는 유일한 방법은 void 포인터를 객체 포인터로 다시 캐스팅하는 것입니다 (저자가 포인터가 무엇을 의미하는지 알아야 함). void 그 자체는 불완전한 유형이므로 객체의 유형은 결코 없으므로 공허 포인터는 객체를 식별하는 데 사용할 수 없습니다. (객체는 유형과 주소로 공동으로 식별됩니다.)

Char에는 특별한 소멸의 논리가 없기 때문입니다. 이것은 작동하지 않습니다.

class foo
{
   ~foo() { printf("huzza"); }
}

main()
{
   foo * myFoo = new foo();
   delete ((void*)foo);
}

d 'ctor는 호출되지 않습니다.

Void*를 사용하려면 Malloc/Free 만 사용하지 않겠습니까? New/Delete는 단순한 메모리 관리 이상입니다. 기본적으로 새/삭제는 생성자/파괴자를 호출하며 더 많은 일이 진행되고 있습니다. 내장 유형 (char*와 같은)을 사용하여 void*를 통해 삭제하는 경우 작동하지만 여전히 권장되지 않습니다. 결론은 void*를 사용하려면 malloc/free를 사용하는 것입니다. 그렇지 않으면 편의를 위해 템플릿 함수를 사용할 수 있습니다.

template<typename T>
T* my_alloc (size_t size)
{
   return new T [size];
}

template<typename T>
void my_free (T* ptr)
{
   delete [] ptr;
}

int main(void)
{
    char* pChar = my_alloc<char>(10);
    my_free(pChar);
}

당신이 정말로 이것을해야한다면, 왜 중간 남자 ( new 그리고 delete 운영자) 및 글로벌에 전화하십시오 operator new 그리고 operator delete 곧장? (물론, 당신이 도구를하려고한다면 new 그리고 delete 운영자, 당신은 실제로 상환해야합니다 operator new 그리고 operator delete.)

void* my_alloc (size_t size)
{
   return ::operator new(size);
}

void my_free (void* ptr)
{
   ::operator delete(ptr);
}

와 다릅니다 malloc(), operator new 던졌습니다 std::bad_alloc 실패시 (또는 new_handler 등록 된 경우).

많은 사람들이 이미 공간 포인터를 삭제하는 것이 안전하지 않다고 이미 언급했습니다. 나는 그것에 동의하지만, 또한 연속 배열이나 이와 유사한 것을 할당하기 위해 Void Pointers로 작업하는 경우 다음과 같이 할 수 있다고 덧붙이고 싶었습니다. new 당신이 사용할 수 있도록 delete 안전하게 (Ahey, 약간의 추가 작업). 이것은 메모리 영역 ( '경기장'이라고 함)에 대한 공허 포인터를 할당 한 다음, 아레나에 대한 포인터를 New에 제공함으로써 이루어집니다. 이 섹션을 참조하십시오 C ++ FAQ. 이것은 C ++에서 메모리 풀을 구현하는 일반적인 접근법입니다.

이것을 할 이유가 거의 없습니다.

우선, 당신이 모르는 경우 유형 데이터 중에서도 아는 것은 void*, 그럼 당신은 그 데이터를 유형으로 처리해야합니다. 얼룩 이진 데이터의unsigned char*)) 및 사용 malloc/free 그것을 다루기 위해. 이것은 때때로 파형 데이터 등과 같은 것들에 필요합니다. void* C API에 대한 포인터. 괜찮아.

만약 너라면 하다 데이터의 유형을 알고 있습니다 (즉, CTOR/DTOR가 있습니다). 어떤 이유로 든 결국 void* 포인터 (어떤 이유로 든) 그러면 정말로 당신이 알고있는 유형으로 다시 캐스팅해야합니다., 그리고 전화 delete 그 위에.

나는 코드 리플렉션 및 기타 모호성 문제를 해결하는 동안 내 프레임워크에서 void*(일명 알 수 없는 유형)를 사용했으며 지금까지 어떤 컴파일러에서도 문제(메모리 누수, 액세스 위반 등)가 발생하지 않았습니다.비표준 작업으로 인한 경고만 표시됩니다.

알 수 없는 항목(void*)을 삭제하는 것은 완벽하게 합리적입니다.포인터가 다음 지침을 따르는지 확인하세요. 그렇지 않으면 포인터가 이해되지 않을 수 있습니다.

1) 알 수 없는 포인터는 간단한 분해자가 있는 유형을 가리켜서는 안 되므로 알 수 없는 포인터로 캐스팅될 때 절대로 삭제되어서는 안 됩니다.알 수 없는 포인터를 ORIGINAL 유형으로 다시 캐스팅한 후에만 삭제하세요.

2) 인스턴스가 스택 경계 또는 힙 경계 메모리에서 알 수 없는 포인터로 참조되고 있습니까?알 수 없는 포인터가 스택의 인스턴스를 참조하는 경우 절대로 삭제하면 안 됩니다!

3) 알 수 없는 포인터가 유효한 메모리 영역이라고 100% 확신하십니까?아니요, 그렇다면 절대로 삭제하면 안 됩니다!

전체적으로 알 수 없는(void*) 포인터 유형을 사용하여 수행할 수 있는 직접적인 작업은 거의 없습니다.그러나 간접적으로 void*는 데이터 모호성이 필요할 때 C++ 개발자가 의지할 수 있는 훌륭한 자산입니다.

버퍼를 원한다면 Malloc/Free를 사용하십시오. 새/삭제를 사용해야하는 경우 사소한 래퍼 클래스를 고려하십시오.

template<int size_ > struct size_buffer { 
  char data_[ size_]; 
  operator void*() { return (void*)&data_; }
};

typedef sized_buffer<100> OpaqueBuffer; // logical description of your sized buffer

OpaqueBuffer* ptr = new OpaqueBuffer();

delete ptr;

숯의 특별한 경우.

Char는 특수 소멸자가없는 고유 유형입니다. 따라서 누출 논쟁은 무시 무시한 논쟁입니다.

크기 (char)는 일반적으로 하나이므로 정렬 인수도 없습니다. 크기 (char)가 하나가 아닌 희귀 플랫폼의 경우, char에 충분히 정렬 된 메모리를 할당합니다. 따라서 정렬 인수는 또한 무의미한 주장입니다.

이 경우 Malloc/Free가 더 빠릅니다. 그러나 당신은 std :: bad_alloc을 상실하고 Malloc의 결과를 확인해야합니다. 글로벌 신규 및 삭제 운영자를 호출하는 것이 중동을 우회 할 때 더 나을 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top