Цель C: [MyObject alloc] теперь вылетает под iOS SDK 4.1 - PullRequest
0 голосов
/ 16 сентября 2010

Я работаю над существующей кодовой базой большого размера, и после обновления iOS SDK до 4.1 теперь я вижу очень странное поведение. Суть дела в том, что конкретный класс больше не будет выделяться - он выбрасывает неправильный доступ в obj_msgSend и, похоже, является объектом Class в стеке, который objc_msgSend не нравится - хотя на самом деле он не равен NULL.

Исходная ошибочная строка выглядела так: -

tileProjection = [[RMFractalTileProjection alloc] initFromProjection:proj tileSideLength:sideLength maxZoom:18];

Я разобрал это, чтобы изолировать проблему: -

RMFractalTileProjection *p = [RMFractalTileProjection alloc];  // <- this crashes
p = [p initFromProjection:proj tileSideLength:sideLength maxZoom:18];
tileProjection = p;

Затем я попробовал это: -

Class c = NSClassFromString(@"RMFractalTileProjection");
assert(c);
NSLog( @"RMFractalTileProjection class(ptr) %p", c );  // <- prints an address OK
NSLog( @"RMFractalTileProjection class(obj) %@", c );  // <- crashes

В отладчике похоже, что объект Class разумный, но NSLog падает, когда пытается его напечатать.

Следует отметить одну вещь: рассматриваемый класс объявлен, как показано ниже, и я не уверен, вызывает ли протокол проблему. Поскольку эта конкретная часть представляет собой большую часть открытого исходного кода, очень трудно удалить это требование протокола, чтобы понять, имеет ли это значение.

@interface RMFractalTileProjection : NSObject<RMMercatorToTileProjection>
{
 ...
}

Любая помощь по этому вопросу очень ценится - это шоу шоу.

Спасибо

Ответы [ 3 ]

1 голос
/ 17 сентября 2010

ОК, наконец-то нашел это. Как предположил Джереми, это оказалось обычным раздражителем памяти.

Трудность, с которой я столкнулся, заключалась в том, что топтался не сам объект Class, а структура метакласса класса - который является обычным объектом Class, но на один уровень выше, на который ссылается указатель класса isa , Вот почему класс выглядел хорошо для меня, когда я проверял его в отладчике - мне нужно проследить указатель isa и сбросить память на один уровень вверх, чтобы найти это. К счастью для меня, класс был только подклассом NSObject - если бы он был глубоко подклассом, найти его было бы гораздо сложнее. Я получил свою первую подсказку после прикуса пули, обратного инжиниринга objc_msgSend, точно выяснив, что было в кадре стека, и следуя всем указателям. Да, трудный путь:)

Пост Мэтта Галлагара (и другие, которые я нашел по ссылкам) оказали неоценимую помощь в этом лабиринте - спасибо, ребята!

Сгорел много времени на этом, но, с другой стороны, я много узнал о внутренних предметах Objective C за последние полтора дня:)

1 голос
/ 16 сентября 2010

Это на самом деле не ответ, но некоторые идеи для продвижения вперед.

Единственные причины, которые приходят на ум в данный момент, - это повреждение памяти и проблема с ссылками. Возможно, вы как-то связываете две версии класса.

Предполагая, , что является классом, нет ничего плохого в том, чтобы заставить его аварийно завершить работу в alloc. Там нет + инициализация или что-нибудь.

Вопросы, которые я бы задавал себе и пытался ответить:

что произойдет, если я переименую класс?

что произойдет, если я создам новый идентичный класс с другим именем?

указатель, который передается obj_msgSend: это разумно? это указывает на что-то, что выглядит как класс?

Вы когда-нибудь делали подкласс класса и используете ли вы инициализацию в подклассе?

всегда ли указатель один и тот же? Если это так, вы можете посмотреть, на что он указывает, и посмотреть, изменится ли он во время выполнения.

что произойдет, если вы отправите себя в класс?

0 голосов
/ 16 сентября 2010

Спасибо за эти предложения JeremyP - всегда полезно иметь свежие предложения после того, как вы весь день бьетесь головой о клавиатуру!

Ваше предложение создать идентичный класс с тем же именем появляется , чтобы решить проблему.Я понятия не имею, почему, и я чувствую, что должен понять, что здесь происходит.Вы правы, это звучит как какая-то проблема с компоновщиком, но я до сих пор не знаю, что может вызвать такую ​​серьезную ошибку во время выполнения и даже не выдавать предупреждение во время сборки.

Re.указатель выглядит разумным, но что-то внутри класса в конце концов разыменовывается как нулевой указатель внутри objc_msgSend.Иногда, после того, как я изменил код и перестроил, вместо этого я получаю нулевой указатель.Такое поведение, очевидно, предполагает что-то недетерминированное, например, помеха памяти.

Я опубликую свои выводы.

...