С эмуляцией карт на базе хоста (HCE) в Android 4.4 вы можете эмулировать протокол ISO / IEC 14443-4. Более конкретно, вы можете эмулировать структуры приложений в соответствии с ISO / IEC 7816-4 (при этом приложения эмуляции карт должны выбираться с помощью AID). Кроме того, API не дает вам никаких средств, чтобы указать, следует ли использовать эмуляцию карты с использованием протокола типа A или типа B.
. Что касается эмуляции различных протоколов MIFARE:
Примечание о функции HCE, доступной в CyanogenMod с версии 9.1 до версии 10.2 : Это будет подражать любому ISO / IEC 14443-4 без требования к структуре приложения в соответствии с ISO / IEC 7816-4. Вы даже можете выбрать, хотите ли вы эмулировать протокол типа A или типа B. Поэтому должно быть возможно (хотя я еще не тестировал), чтобы подражать любому из трех протоколов DESFire. Однако даже с функцией HCE CyanogenMod невозможно эмулировать протоколы MIFARE Ultralight или Classic. Более того, также невозможно влиять на параметры протокола низкого уровня, такие как UID, ATQA, SAK или ATS.
Если вы используете glibc, вы можете установить переменную окружения MALLOC_CHECK_
в 2
, это заставит glibc использовать устойчивую к ошибкам версию malloc
, которая заставит вашу программу прерваться в точке, где выполняется double free.
Вы можете установить это из gdb, используя команду set environment MALLOC_CHECK_ 2
перед запуском вашей программы; программа должна прерваться, при этом вызов free()
будет виден в бэктрейсе.
см. страницу man для malloc()
для получения дополнительной информации
Используете ли вы интеллектуальные указатели, такие как Boost shared_ptr
? Если да, проверьте, используете ли вы где-нибудь напрямую необработанный указатель, вызвав get ()
. Я обнаружил, что это довольно распространенная проблема.
Например, представьте сценарий, в котором исходный указатель передается (например, в качестве обработчика обратного вызова) в ваш код. Вы можете назначить это умному указателю, чтобы справиться с подсчетом ссылок и т. Д. Большая ошибка: ваш код не владеет этим указателем, если вы не сделаете глубокую копию. Когда ваш код завершится с помощью интеллектуального указателя, он уничтожит его и попытается уничтожить память, на которую он указывает, поскольку он думает , что он никому больше не нужен, но вызывающий код будет затем попробуйте удалить его, и вы получите двойную бесплатную проблему.
Конечно, это может не быть вашей проблемой. Вот самый простой пример, который показывает, как это может произойти. Первое удаление - это нормально, но компилятор чувствует, что он уже удалил эту память, и вызывает проблему. Вот почему присвоение 0 указателю сразу после удаления - хорошая идея.
int main(int argc, char* argv[])
{
char* ptr = new char[20];
delete[] ptr;
ptr = 0; // Comment me out and watch me crash and burn.
delete[] ptr;
}
Edit: изменено delete
на delete []
, поскольку ptr - это массив символов.
Есть как минимум две возможные ситуации:
Для первого варианта я настоятельно рекомендую NULL-ить все удаленные указатели.
У вас есть три варианта:
Три основных правила:
NULL
после освобожденияNULL
перед освобождением. NULL
в начале работы. Комбинация этих трех способов работает достаточно хорошо.
Вы можете использовать gdb, но сначала я бы попробовал Valgrind . См. руководство по быстрому запуску .
Вкратце, Valgrind настраивает вашу программу таким образом, чтобы она могла обнаруживать несколько видов ошибок при использовании динамически выделяемой памяти, таких как двойное освобождение и запись после конца выделенных блоков памяти (что может привести к повреждению кучи). Он обнаруживает и сообщает об ошибках , как только они возникают , тем самым указывая вам непосредственно на причину проблемы.