Поймать NSMallocExceptioni с помощью Swift

Время от времени мои пользователи обнаруживают эту ошибку:

myapp(7383,0x1a1471000) malloc: * mach_vm_map(size=67125248) не удалось (код ошибки=3) ошибка: невозможно выделить область установить точку останова в malloc_error_break для отладки 2017-04-06 20:33:58.152 myapp[7383:3724816] Завершение работы приложения из-за необработанного исключения «NSMallocException», причина: « NSAllocateObject(): attempt to allocate object of class 'IOSByteArray' failed' * First throw call stack: (0x183386db0 0x1829ebf80 0x183386cf8 0x183c6b34c 0x10076e6e4 0x10097d3ec 0x10097e35c 0x100977dd4 0x100977bd8 0x100978ff8 0x10096c950 0x10099685c 0x100997360 0x100979ca4 0x100976dcc 0x1002ec30c 0x100332fe4 0x100332e18 0x1003740c4 0x1004070f8 0x1004064ac 0x1021089b0 0x10210806c 0x1021089b0 0x102107710 0x1004072d8 0x1021087ec 0x1004071b0 0x102126bbc 0x10207b2d8 0x10207b374 0x188613dc4 0x1886d17d4 0x18878f0c8 0x18879ca80 0x1884ce5a4 0x18333c728 0x18333a4cc 0x18333a8fc 0x183264c50 0x184b4c088 0x188546088 0x100382a60 0 x182e028b8) libc++abi.dylib: завершение с необработанным исключением типа NSException

Проблема в том, что я не могу найти стек ошибок. Я использую библиотеку XZ java, перенесенную в библиотеку objc с помощью приложения j2objc. Итак, я могу использовать эту библиотеку, но не могу поймать эту ошибку.

Google Analytics помогает мне и показывает эту строку:

"&exd" = "NSMallocException\nTrace:\n\nNSAllocateObject\nIOSByteArray_NewArray\nOrgTukaaniXzLzLZDecoder_initWithInt_withByteArray_\nnew_OrgTukaaniXzLzLZDeco";

Итак, кажется, произошла ошибка:

void OrgTukaaniXzLzLZDecoder_initWithInt_withByteArray_(OrgTukaaniXzLzLZDecoder *self, jint var1, IOSByteArray *var2) {
    NSObject_init(self);
        self->start_ = 0;
        self->pos_ = 0;
        self->full_ = 0;
        self->limit_ = 0;
        self->pendingLen_ = 0;
        self->pendingDist_ = 0;
        JreStrongAssignAndConsume(&self->buf_, [IOSByteArray newArrayWithLength:var1]);
        if (var2 != nil) {
            self->pos_ = JavaLangMath_minWithInt_withInt_(var2->size_, var1);
            self->full_ = self->pos_;
            self->start_ = self->pos_;
            JavaLangSystem_arraycopyWithId_withInt_withId_withInt_withInt_(var2, var2->size_ - self->pos_, self->buf_, 0, self->pos_);
        }
}

Но я не могу найти эту ошибку, используя swift:

do {
// ............
let inxz:OrgTukaaniXzXZInputStream = try OrgTukaaniXzXZInputStream(javaIoInputStream:in_)
// ..........
} catch {
print(error)
}

Помогите пожалуйста мне


person Vyacheslav    schedule 06.04.2017    source источник
comment
убежать от j2objc   -  person Sulthan    schedule 06.04.2017
comment
@Султан, объясни, пожалуйста   -  person Vyacheslav    schedule 06.04.2017
comment
Кажется, это переведенная версия github.com/wikimedia/openzim/blob/master/zimreader-java/src/org/, который вызывается только из LZMA2InputStream.java. Я просмотрел код и не знаю, как это могло вызвать исключение памяти. Либо плохо переведена обработка памяти, вызывающая утечку памяти (используйте обнаружение утечек в инструментах), либо плохо переведены внутренние проверки размера словаря. Обе возможности означают, что перевод неверен. Почему бы вам не использовать версию C напрямую?   -  person Sulthan    schedule 06.04.2017
comment
Другая возможность заключается в том, что вы используете файлы со словарями размером около 2 ГБ, что должно быть очень редко.   -  person Sulthan    schedule 06.04.2017
comment
@Sulthan, я портировал несколько java-библиотек. xz является частью кода - средний шаг. Довольно сложно переписать код, используя чистую C lib.   -  person Vyacheslav    schedule 06.04.2017
comment
@Sulthan, 10 раз за твою идею. Я реализовал собственную библиотеку C вместо j2obj. Теперь не вылетает.   -  person Vyacheslav    schedule 09.04.2017


Ответы (2)


Swift try/catch полностью отделен от исключений ObjC, подобных этому. Их можно поймать только с помощью ObjC, используя @try и @catch. Это невозможно сделать в Swift.

Тем не менее, ObjC, как правило, не является безопасным для исключений. Вы должны быть очень осторожны, используя их, и почти во всех случаях правильным поведением после исключения является сбой программы. В этом случае, обернутом только одним вызовом функции моста, может быть возможно эффективно поймать и обработать, но правильное выполнение этого является довольно тонким навыком и не рекомендуется, если вы можете избежать этого.

Почти наверняка причина этой ошибки в том, что вы пытаетесь выделить что-то слишком большое. Вместо того, чтобы пытаться поймать исключение, я бы посмотрел, почему объект такой большой, и обратился к нему. В частности, я бы посмотрел, насколько велик var1, и убедился, что он находится в разумных пределах. Также убедитесь, что он не отрицательный. Тот факт, что вы используете jint, предполагает, что вы можете видеть несоответствие с вашими целочисленными типами, которые, как я абсолютно уверен, вызовут такой сбой.

person Rob Napier    schedule 06.04.2017
comment
Я использую Eureka lib с расширением/свертыванием содержимого с внутренними обратными вызовами. Итак, пользователь несколько раз пытается декодировать небольшие данные xz. Нет утечки памяти. Не могу ни уловить, ни понять проблему. В любом случае, спасибо. Кажется, мне нужно отредактировать код конвертации вручную. - person Vyacheslav; 06.04.2017

Спасибо @Sultan. Он подал мне идею использовать XZ pure C lib вместо Java>ObjC lib. Сейчас этого краха нет. Кажется, что j2obc — удивительный фреймворк, но в нем есть редкие неуловимые ошибки.

person Vyacheslav    schedule 08.04.2017