Join Now
Quality Rating:
  • Currently 0.0 / 5
(0.0 / 5 - 0 votes cast)
Expertise Level:
  • Currently 0.0 / 5
(0.0 / 5 - 0 votes cast)

This page was last modified 21:47, 27 May 2008.

Методы отладки

From Forum Nokia Wiki

Перевод с английского, оригинальная статья находится здесь.


Contents

Эмулятор не отображает параметры возникшей паники

При возникновении паники, эмулятор отображает ее параметры только в том случае, если файл с именем "ErrRd" существует в определенной папке. Если такого файла нет, отображается сообщение следующего вида:

Image:Panic.jpg

По такому сообщениию трудно определить причины возникновения паники.

В предыдущих версиях SDK (до 3-го издания) файл ErrRd нужно было создавать вручную, начиная с 3-го издания этот файл существует по умолчанию в папке "\Symbian\9.2\S60_3rd_FP1\Epoc32\winscw\c\resource". При наличии этого файла информация о возникшей панике отображается следующим образом:

Image:Panic_with_ErrRd.jpg

Совет: Если вы используете SDK для 3-го издания, однако файл ErrRd найти не можете, воспользуйтесь меню эмулятора Tools > Preferences и выберите Extended panic code file.

Поиск ошибок с помощью утверждений

Утверждения используются для проверки корректности значений различных переменных, например с их помощью можно проверить параметры функций, возвращаемые значения, состояния объектов и т.д. Для реализации утверждений в Symbian предусмотрено два макроса __ASSERT_ALWAYS и __ASSERT_DEBUG. Разница заключается в том, что __ASSERT_ALWAYS работает всегда, в то время как __ASSERT_DEBUG только в отладочных версиях программы.

Макросы, с помощью которых выполняется проверка утверждений, по умолчанию не генерируют панику. Конкретные действия в случае если утверждение неверно, разработчик должен определять сам. Генерация паники является предпочтительным вариантом действия.

Пример использования:

void TestValue(TInt aValue)
{
  _LIT(KPanicCategory, "TestValue");
  __ASSERT_DEBUG((aValue >= 0), User::Panic(KPanicCategory, 99));
  // Выполнение функции
  // ...
}

В этом примере генерируется паника -99 в случае если aValue меньше нуля. Проверка срабатывает только в отладочной версии программы.

Если нет необходимости обрабатывать сгенерированную в результате неверного утверждения панику, можно воспользоваться макросом ASSERT. При использовании ASSERT не нужно определять параметры выбрасываемой паники.

Определение этого макроса в файле e32def.h:

#define ASSERT(x) __ASSERT_DEBUG(x, User::Invariant())

Пример использования

void TestValue(TInt aValue)
{
  ASSERT(aValue >= 0);
  // Выполнение функции
  // ...
}


Определение утечек памяти с помощью макросов __UHEAP_MARK и __UHEAP_MARKEND

Макросы __UHEAP_MARK и __UHEAP_MARKEND позволяют определить, насколько корректно ваше приложение использует динамическую память (нет ли утечек).

Пример использования:

GLDEF_C TInt E32Main()
{
  // Начало проверки наличия утечек памяти
  __UHEAP_MARK;
 
  // Создаем массив из 10 элементов в куче
  CArrayFixFlat<TInt>* fixFlatArray;
  fixFlatArray = new(ELeave) CArrayFixFlat<TInt>(10);
  // Массив не был удален - возникла утечка памяти
 
  // Окончания проверки - генерация паники
  __UHEAP_MARKEND;
 
  return KErrNone;
}

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

Image:Memory_leak_MACRO.jpg

Стоит отметить, что эти макросы работают только в отладочной версии программы и никак не влияют на итоговую версию программы.


Макросы для контроля инвариантности объектов

Существуют два системных макроса с помощью которых можно выполнить проверку состояния объекта: __DECLARE_TEST и __TEST_INVARIANT. На практике эти макросы используются следующим образом: создается функция которая выполняет проверку состояния объекта, далее эта функция вызывается в коде, где эта проверка необходима (обычно в начале и в конце функции, которая изменяет состояние объекта). Ниже представлен пример использования данных макросов - класс CLivingPerson хранит информацию о человеке и контролирует значения пола и возраста.

class CLivingPerson : public CBase
{
public:
  enum TGender {EMale, EFemale};
public:
  CLivingPerson(TGender aGender);
  ~CLivingPerson();
public:
  void SetAge(const TInt aAge);
private:
  TGender iGender;
  TInt iAgeInYears;
  __DECLARE_TEST;  // тестирование инвариантности объекта
};
 
CLivingPerson::CLivingPerson(TGender aGender) : iGender(aGender) {}
CLivingPerson::~CLivingPerson() {}
 
void CLivingPerson::SetAge(const TInt aAge)
{
  // установка возраста и контроль инвариантности
  __TEST_INVARIANT;
  iAgeInYears = aAge;
  __TEST_INVARIANT;
}
 
void CLivingPerson::__DbgTestInvariant() const
{
  #ifdef _DEBUG  // Только для отладочной версии
  // Пол должен быть определен корректно
  ASSERT((iGender == EMale) || (iGender == EFemale));
  
  // Возраст не может быть отрицательным
  ASSERT(iAgeInYears >= 0);
  #endif
}

Если состояние объекта некорректное (возраст или пол определены неверно), будет сгенерирована паника USER 0.


Определение некорректного использования стека очистки

Объекты должны извлекаться из стека очистки, если далее в коде нет опасности возникновения сброса. Соответственно, извлечение из стека обычно осуществляется для того чтобы удалить объект. Для реализация извлечения из стека и последующего гарантированного удаления можно использовать функцию PopAndDestroy, которая позволяет избежать возникновения утечек памяти.

Обе функции CleanupStack::Pop и CleanupStack::PopAndDestroy имеют перегруженные варианты, которые принимают в качестве параметра "ожидаемый элемент", который должен быть извлечен из стека. В случае если этот параметр не равен элементу на вершине стека, генерируется паника E32USER-CBase 90. Благодаря такой реализации, можно обнаружить некорректное использование стека очистки.

CClass* obj = new(ELeave) CClass;
CleanupStack::PushL(obj);
// ...
// Генерируется паника, если "obj" не на вершине стека
CleanupStack::PopAndDestroy(obj);

Замечание: Проверка параметра на вершине стека осуществляется только в отладочной версии программы, в итоговой версии данная проверка не используется.

Related Discussions
Thread Thread Starter Forum Replies Last Post
Проблема с CCalEntryView::FetchL() truf Russian Developer Forum - Форум Российских разработчиков 7 2008-04-04 18:51
Ошибка компиляции 3bepek Russian Developer Forum - Форум Российских разработчиков 11 2007-12-11 08:59
Forum Nokia Wiki (русскоязычный портал) - Ваши пожелания Ecconaut Russian Developer Forum - Форум Российских разработчиков 27 2008-04-15 19:50
SyncML Task Id igor_k11 Russian Developer Forum - Форум Российских разработчиков 4 2008-09-30 09:32
RMobileUssdMessaging truf Russian Developer Forum - Форум Российских разработчиков 30 2008-02-16 19:05
 
Powered by MediaWiki
     
     RDF Facets:
     
     
     qfnZtypeQUqfnTypeZCommunityContentQ
     qfnZtypeQUqfnTypeZWebpageQ
     qfnZtypeQUqfnTypeZWikiContentQ
     qmarsZlanguageQUxhttpE3aE2fE2fswE2enokiaE2ecomE2flanguageE2d1E2fenX