1

내가 이런 식으로 스택에 변수 크기의 배열을 할당하고, 가능 :alloca 함수와 오브젝티브 -c의 가비지 콜렉터

MaValue *myStack = alloca((sizeof(id) * someLength)); 

(나는이 작업을 수행 할 수있는 이유는 중요하지 않습니다 :) 그런 다음, 루프 내에서 myStack의/from 항목을 밀고 팝합니다. 스택에 밀어 붙이는 것들 중 일부는 다른 곳에서 참조되지 않은 새로운 객체입니다.

객관적인 C 가비지 수집기는 해당 포인터에 대해 알지 못하므로 새 (그렇지 않으면 참조되지 않은) 개체를 수집합니다. 그러한 믿음의 일부는 객관적인 C GC가 실제로 보수적이지는 않지만 (예를 들어 스택 맵을 통해) "그 포인터를 안다"는 생각에서 나온다.

그러나 모든 실험 ([NSGarbageCollector defaultCollector] collectExhaustively] 호출을 삽입 할 때)이 객체를 수집하지 못했습니다. 이는 훌륭하지만 예상치 못한 결과입니다. 그래서 GC가 전체 스택을 스캔하고 있으며, 예를 들어 보수적으로 실제 포인터 값이되는 정수가 있다고 가정합니다.

맞습니까? 또는 나는 무엇인가 놓치고 있냐?

+0

'MaValue 'Objective-C 클래스 타입? 그렇다면 객체에 대한 포인터의 배열이기 때문에 포인터를 가리키는 포인터 인'MaValue ** myStack = ...'으로 선언해야합니다. 각 객체 인스턴스는 여전히 힙에 할당하면 GC가 메모리 관리를 대신 처리하며 스택에 Objective-C 객체 인스턴스를 가질 수없고 포인터 만 사용할 수 있습니다. –

답변

3

올바르게 작동합니다.

각 클래스가 레이아웃을 갖고 오브젝트를 참조하거나 __strong을 사용하는 슬롯 만 스캔하도록 콜렉터가 가능한 한 정확하게 힙을 스캔하지만 스택은 보수적으로 스캔해야합니다. 스택의 모든 포인터 크기 및 포인터 정렬 슬롯은 참조를 위해 스캔해야합니다.

따라서 alloca()는 스택 포인터를 아래로 내리고 콜렉터는 모든 포인터를 스캔합니다. 비헤이비어가 정의되지 않았으므로 alloca'd 공간이 포인터로 정렬되도록 assert를 던져야합니다.

실제로 실제로 alloca()를 사용하면 안됩니다. 맨 페이지에서도 다음과 같이 말합니다 :

alloca() 함수는 machine이고 컴파일러에 따라 다릅니다. 그 사용은 입니다.

대신 NSAllocateCollectable()을 사용하여 스캔 한 힙 공간을 할당하십시오. 많은 할당과 다른 작업에 대해 이야기하지 않는 한 오버 헤드는 최소화되어야합니다. 게다가 더 이상 스레드의 최대 스택 크기를 초과 할 위험이 없습니다. (큰 것이 아니며 실행중인 스레드와 할당 방식에 따라 달라집니다.)

관련 문제