Obecnie próbuję zaimplementować system poolingu, mam cały kod, po prostu nie rozumiem, dlaczego pewna jego część nie działa.

Mam tablicę c tablicy NSMutable wykonaną w ten sposób:

    NSMutableArray *poolArray[xSize][ySize];
    for (int n = 0; n < xSize; n++) 
    {
        for (int m = 0; m < ySize; m++)
        {
            poolArray[n][m] = [[NSMutableArray alloc] init];
        }
    }

I próbując uzyskać do niego dostęp, otrzymuję współrzędne x i y puli i obiektu i próbuję dodać to w ten sposób:

[poolArray[x][y] addObject:object]; //This raises a EXC_BAD_ACCESS error

Jestem całkowicie otwarty na edycję tego, jak to piszę - zdaję sobie sprawę, że mógłbym zadeklarować NSMutableArray i użyć indeksów ((y * szerokość) + x) i być może będę musiał przepisać kod w ten sposób. Ale najlepiej nie chcę tego robić, ponieważ chcę tylko tworzyć tablice, których używam, więc coś takiego:

if (poolArray[x][y] == nil) poolArray[x][y] = [[NSMutableArray alloc] init];
[poolArray[x][y] addObject:object];

Jest tak, że może mieć „dziury”, więc nie muszę nic robić w poolArray[2][3], na przykład, jeśli nic tam nie ma.

Nie wiem, czy i tak mógłbym to przepisać za pomocą typów obiektywnych-c, ale jeśli to zrobię, jestem zmuszony do dalszego tworzenia NSMutableArray w każdym miejscu, powodem, dla którego nie chcę tego robić, jest to, że chcę uzyskać z systemu każdą odrobinę wydajności, jaką mogę.

Dziękujemy za poświęcenie czasu na przeczytanie tego, a każda odpowiedź jest mile widziana :)

1
MPainter 24 sierpień 2011, 17:41

2 odpowiedzi

Najlepsza odpowiedź

Nie widzę nic złego w dostarczonym przez Ciebie kodzie, chociaż kilka pomysłów:

W przypadku, gdy sprawdzasz poolArray[x][y] == nil, czy rzeczywiście zresetowałeś wszystkie wartości do nil podczas inicjalizacji tablicy?

Alternatywą, która powinna działać, jest przechowywanie tablicy na stercie. Możesz użyć calloc (który zainicjuje pamięć do 0) lub malloc i memset.

Powinno działać:

NSMutableArray ***poolArray = calloc(xSize * ySize, sizeof(NSMutableArray *));

if (poolArray[x][y] == nil) poolArray[x][y] = [[NSMutableArray alloc] init];
[poolArray[x][y] addObject:object];
1
Tom Jefferys 24 sierpień 2011, 17:56
Ustawienie obiektów na zero sprawia, że ​​to działa! Kiedy to zrobiłem, spowodowało to również awarię w momencie wydania puli automatycznego zwalniania, ale przeczytałem gdzieś, że gdy nie zachowujesz obiektu (jak to robię z NSMutableArray), jest on zwalniany automatycznie, ale następnie zwalniam go na końcu moja metoda i domyślam się, co spowodowało awarię, było to, że pula autorelease próbowała zwolnić obiekt, który nie istniał! Dzięki za pomoc, nadal mam kilka problemów z systemem, ponieważ nie rozpoznaje kolizji, ale jestem prawie pewien, że jest to problem w innym miejscu kodu, ponieważ teraz się nie zawiesza!
 – 
MPainter
24 sierpień 2011, 23:04

To działa dla mnie:

#import <Foundation/Foundation.h>

#define xSize 10
#define ySize 10

int main (int argc, const char * argv[])
{

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSMutableArray *poolArray[xSize][ySize];
    for (int n = 0; n < xSize; n++) 
    {
        for (int m = 0; m < ySize; m++)
        {
            poolArray[n][m] = [[NSMutableArray alloc] init];
        }
    }

    [poolArray[2][3] addObject: @"Hello"];
    [poolArray[2][3] addObject: @"world!"];
    NSLog(@"poolArray[2][3] objects: %@ %@", 
              [poolArray[2][3] objectAtIndex: 0],
              [poolArray[2][3] objectAtIndex: 1]);

    [pool drain];
    return 0;
}

(Tak, wiem, powinienem zwolnić wszystkie instancje NSMutableArray. Pominięto dla zwięzłości).

Jest więc kilka rzeczy, które powinieneś sprawdzić:

  • Czy object jest prawidłowym obiektem, tj. czy został zainicjowany? NSMutableArray spróbuje retain obiektu, a jeśli nigdy nie został zainicjowany, zakończy się niepowodzeniem lub jeśli został już dealloc-edytowany, również się nie powiedzie.
  • czy x i y są ważne? Możesz łatwo przekroczyć granice i tego nie zauważyć.
2
Rudy Velthuis 24 sierpień 2011, 18:09
Po prawej przejrzałem cały kod w debugerze, ponieważ wszystkie rozmiary są obliczane w czasie wykonywania, a xSize i ySize wynoszą 2. Podczas przechodzenia przez pętle, w których generowane są x i y, wynoszą one: 1,1 1,0 0, 1 0,0 więc żadna z nich nie jest niepoprawną wartością, chyba że się mylę, a obiekt pochodzi z obiektu w mojej grze, wiem, że jest zainicjowany, ponieważ bez tego kodu działa i renderuje ect dobrze, kiedy to zrobiłem, chociaż kod został wykonany poprawnie i uległ awarii, gdy dotarł do metody automatycznego zwalniania puli
 – 
MPainter
24 sierpień 2011, 22:53
1
Wtedy prawdopodobnie zbytnio uwolniłeś (lub nie zatrzymałeś) przedmiot lub przedmioty, których używasz.
 – 
Rudy Velthuis
24 sierpień 2011, 22:57
1
Lub, o wiele bardziej prawdopodobne, ty lub coś automatycznie zwolniło twój obiekt. Oznacza to, że będzie działać przez chwilę, dopóki nie natkniesz się na drenaż lub zwolnienie releasePool. Po prostu zatrzymaj go tam, gdzie go dostaniesz i wypuść go w odpowiednim czasie.
 – 
Rudy Velthuis
24 sierpień 2011, 23:10