Я столкнулся с той же проблемой, пытаясь все, комментируя блок пакета исправил проблему для меня
/*bundle {
language {
enableSplit = false
}
density {
enableSplit = false
}
abi {
enableSplit = true
}
}*/
Я не уверен, что это правильный подход, но после сборки проекта и генерации apk У меня есть файл .aar, который, я думаю, и есть то, что вы пытаетесь получить.
Из того, что я вижу, этот код должен всегда приводить к ошибке. FreeAndNil явно устанавливает, который передал значение Нолю (иначе 0), таким образом, необходимо абсолютно получить нарушение прав доступа при попытке разыменовать объект.
Всегда неправильно использовать методы или свойства нулевой ссылки, даже если это, кажется, иногда работает.
FreeAndNil
действительно не может использоваться для обнаружения, дважды освобождает. Безопасно звонить FreeAndNil
на уже-нулевой переменной. Так как это безопасно, это не помогает Вам обнаружить что-либо.
Это не ошибка устаревшего указателя. Это - ошибка нулевой ссылки. Ошибка устаревшего указателя - когда Вы освободили объект, но не очистили все переменные, которые сослались на нее. Затем переменная все еще содержит старый адрес объекта. Это очень трудно обнаружить. Можно получить такую ошибку как это:
MStr := TMemoryStream.Create;
MStr.Free;
MStr.Size := 0;
Можно также получить один как это:
MStr := TMemoryStream.Create;
OtherStr := MStr;
FreeAndNil(MStr);
OtherStr.Size := 0;
Используя MStr.Size
после освобождения объекта MStr
ссылаемый ошибка, и она должна повысить исключение. Повышает ли это действительно исключение, зависит от реализации. Возможно, это будет, и возможно это не будет. Это не случайно, все же.
При поиске бездвойной ошибки можно использовать помощников отладки, которых предоставляет FastMM, как другие предположили также. Это работает путем не на самом деле освобождения памяти назад к операционной системе, или даже назад к внутреннему пулу свободной памяти Delphi. Вместо этого это пишет известные неправильные данные в пространство памяти объекта, поэтому когда Вы будете видеть те значения, Вы будете знать, что читаете из чего-то, что Вы уже освободили. Это также изменяет VMT объекта так, чтобы в следующий раз Вы назвали виртуальный метод на той ссылке на объект, Вы получите предсказуемое исключение, и это даже скажет Вам, которые, предположительно, освободили объект, который Вы пытались использовать. Когда Вы пытаетесь освободить объект снова, он может сказать Вам не только, что Вы уже освободили его, но также и где он был освобожден в первый раз (с отслеживанием стека), и где он был выделен. Это также собирает ту информацию для создания отчетов об утечках памяти, где Вы освободили объект меньше чем в один раз вместо больше.
Существуют также привычки, которые можно использовать для предотвращения проблемы для будущего кода:
FreeAndNil
на его переменной, это все еще отпуск неизменная переменная другого кода. Если тот другой код думает, что владеет объектом, то Вы в беде. (Это понятие о владельце не обязательно связывается с TComponent.Owner
свойство. Не должно быть объекта, который владеет им; это могла быть общая подсистема Вашей программы.)Только усложнить проблему:
Если метод, который Вы называете, будет помехами (не виртуальный) метод, и это не называет виртуальных методов само, и при этом это не получает доступ ни к каким полям объекта, то Вы не получите нарушение прав доступа, даже если ссылка на объект была установлена на NIL.
Причина этого состоит в том, что нарушение прав доступа вызывается путем разыменования сам указатель (в этом случае NIL), но который только происходит при доступе к полю или VMT объекта для вызова виртуального метода.
Это - просто исключение из правила, что Вы не можете назвать методы ссылки на объект NIL, которую я хотел бы упомянуть здесь.
При установке указателя на ноль Вы не должны мочь использовать его больше. Но если у Вас есть другой указатель на тот же объект, можно использовать его, не получая AV, потому что этот указатель неподвижные точки к объектному адресу а не к нолю.
Кроме того, освобождение объекта не очищает память, используемую тем объектом. Это просто отмечает его как не используемый. Это - причина, которую Вы хотите, получают AV. Если освобожденная память будет выделена для другого объекта, то Вы получите AV, потому что это больше не содержит данные, которые кажутся допустимыми.
FastMM4 имеет некоторые настройки, которые можно использовать при отладке, который обнаружит такие условия. От FsatMM4Options.inc:
{Устанавливают следующую опцию сделать обширную проверку всех блоков памяти. Все блоки дополнены и заголовком и трейлером, которые используются для проверки целостности "кучи". Освобожденные блоки также очищены к гарантировать, что они не могут быть снова использованы, будучи освобожденным. Эта опция замедляет операции памяти существенно и должна только использоваться для отладки приложения, которое перезаписывает память или снова использует освобожденные указатели. Установка этой опции автоматически включает CheckHeapForCorruption и отключает ASMVersion. Очень важный: при включении этой опции приложение потребует библиотеки FastMM_FullDebugMode.dll. Если эта библиотека не будет доступна, то Вы получите ошибку на запуске.}
{$define FullDebugMode}
Другая кавычка из того же файла:
FastMM всегда ловит попытки освободить тот же блок памяти дважды...
Поскольку Дельфи использует FastMM от Delphi 2007 (2006?), необходимо получить ошибку при попытке к doublefree объекта.
Thomas Mueller: Вы попробовали виртуальные методы класса? Конструктор является видом виртуального метода, но Вы называете его против типа - не экземпляр. Это означает, что даже некоторые определенные виртуальные методы не вызовут AV на нулевой ссылке :D
Vegar: Вы не могли быть более правыми! FastMM является лучшим когда-либо когда-либо когда-либо инструмент, который помог мне разыскивающий этот вид ошибок.
Блог EureyLog имел отличный пост об этом в апреле 2009 года:
Почему вы всегда должны использовать FreeAndNil вместо Free.