Отладка программы на C++ в visual studio 2010

Рубрика: Visual Studio, Дата: 3 August, 2014, Автор:

Этапы написания программыЗдорова господа! Я давно уже хотел написать статью о том как пользоваться отладкой в visual studio 2010, я сам правда не сильно знаю, от поэтому и пишу статью, что б разобраться и потом если что подсмотреть как ей пользоваться.

Что такое отладка? Отладка (debugging) – это процесс нахождения ошибок и их устранения. Как видим из графика слева основное время в написании программы у программиста уходит на отладку программы ДЕБАГ. Несомненно, вы уже знаете, что отладка – неотъемлемая часть процесса программирования.

Программы, превышающие некоторый порог размера и сложности, всегда содержат ошибки, независимо от того, сколько времени и усилий было потрачено на их проверку. (Мера сложности и величина, гарантирующая наличие ошибок, не может быть определена точно, но среда разработки Visual C++ 2010 и ваша операционная система определенно подпадают под эту категорию!)

Содержание:

1. Базовые операции отладки
2. Установка точек останова
3. Расширенные точки останова
4. Установка точек трассировки
5. Запуск отладки
6. Добавление отладочного кода
7. Использование Утверждений
8. Добавление собственного отладочного кода
9. Отладка программы
10. Функции проверки динамической памяти.
10. Резюме.


Базовые операции отладки

Отладчик  – это программа, которая контролирует выполнение вашей программы таким образом, что вы можете пошагово выполнять код, строку за строкой, или же запустить его до определенной точки в программе.

В каждой точке программы, где отладчик останавливается, можно посмотреть (и даже изменить) значения переменных, прежде чем продолжить выполнение. Можно изменить исходный код, перекомпилировать, а затем перезапустить программу сначала. Можно даже изменить исходный код посреди пошагового выполнения программы. При переходе к следующему оператору после модификации кода отладчик автоматически перекомпилирует программу перед выполнением следующего оператора.

Чтобы понять базовые средства отладки среды разработки Visual C++ 2010, используйте отладчик в программе, которая, как вы уверены, работает правильно. Вы сможете просто заглянуть в ее “внутренности” и увидеть, что там происходит. Возьмем простой пример, использующий указатели.

Показать »

#include <iostream>
using namespace std;

int main()
{
	long* pnumber(nullptr);
	long number1=55, number2=99;
	pnumber=&number1;
	*pnumber+11;
	cout <<endl
		<<"number1 = "<<number1
		<<" &number1 = "<<hex<<pnumber;

	pnumber=&number2;
	number1=*pnumber*10;

	cout <<endl
		<<"number1= "<<dec<<number1
		<<" pnumber= "<<hex<<pnumber
		<<" *pnumber= "<<dec<<*pnumber;

	cout <<endl;

	return 0;
}

вывод:

QIP Shot - Screen 126

Мы можем выполнить этот пример по одному оператору за раз и наблюдать за содержимым интересующих переменных.

Прежде всего следует убедиться, что конфигурация сборки примера установлена в Win32 Debug, а не Win32 Release.

QIP Shot - Screen 127

Можно также использовать меню Построение -> диспетчер конфигурации и в открывшемся окне посмотретьQIP Shot - Screen 128QIP Shot - Screen 129

Конфигурация проекта Debug включает дополнительную информацию в вашу исполняемую программу во время компиляции, что позволяет потом использовать возможности отладки.

Для того чтобы запустить отладчик, щелкните на крайней слева кнопке панели инструментов Debug, выберите пункт меню Debug=>Start Debugging (Отладка => Начать отладку) либо нажмите клавишу <F5>.QIP Shot - Screen 130Отладчик имеет два главных режима выполнения – пошаговое выполнение кода (т.е. выполнение по одному оператору программы за раз) и выполнение до определенной точки, указанной в исходном коде. Точки в исходном коде, где отладчик приостанавливает выполнение программы, называется точкой останова (breakpoint).

 Установка точек останова

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

Чтобы установить точку останова в начале строки исходного кода, щелкните на серой колонке слева от номера строки с оператором, перед которым хотите остановить выполнение. В ней появится красный кружок, называемый глифом (glyph), указывающий на точку останова в строке. Удалить эту точку можно с помощью двойного щелчка.QIP Shot - Screen 131

Расширенные точки останова

Более совершенный способ установки точек останова предлагается в окне, которое открывается с помощью комбинации клавиш <Alt+F9> или выбора пункта Breakpoints(Точки останова) из списка, отображаемого при выборе кнопки Windows(Окна) панели инструментов Debug, которая находится в ее правой части

QIP Shot - Screen 132появится окно

Окно точек останова в этом окне вы можете также настраивать точки останова, просто посмотрите что там есть, попробуйте понажимать по кнопкам.

Дополнительные параметры для точки останова устанавливаются целчком правой кнопкой мыши на строке останова в окне Breakpoints и выбором соответствующих пунктов из контекстного меню. Наряду с установкой точки останова в определенном месте кода можно также установить точку останова когда определенное логическое выражение вернет значение true. Это мощное средство, но оно влечет за собой очень существенные накладные расходы при выполнении программы, поскольку проверочное выражение должно постоянно вычисляться.

Установка точек трассировки

Точка трассировки(tracepoint) – разновидность точки останова, с которой связано некоторое специальное действие. Такая точка создается щелчком правой кнопкой мыши на строке, где ее нужно установить, и выбором пункта Breakpoint=>When Hit(Точка останова=>При попадании) из контекстного меню. Откроется диалоговое окно When Breakpoints Hit(Когда происходит попадание в точку останова).QIP Shot - Screen 134Появится окошко настроек, в нем выбираем настраиваем точку трассировки, ну я ее не сильно разбирал, та читайте экспериментируйте как что настраивать. QIP Shot - Screen 135Вписываем в текстовое поле

Function: $FUNCTION, Thread: $TID $TNAME

и в данном случае выведется в окно “вывод” название текущей функции и еще что то означающее $TID-идентификатор потока $TNAME-имя потока. Можно вывести значение переменной указав ее в фигурных скобках {pname} выведет значение переменной pname.

QIP Shot - Screen 136Запуск отладки

Существует пять способов запуска приложения в режиме отладки через меню Debug (Отладка), которое показано нижеменю отладка

  1. Пункт Start Debugging (Начать отладку), доступный и как кнопка панели инструментов Debug, просто запускает программу до первой точки останова (если она есть), где выполнение будет приостановлено. После того как вы просмотрите все необходимое в этой точке, выбор того же пункта меню или той же кнопки панели инструментов продолжит выполнение вплоть до следующей точки останова. Подобным образом можно передвигаться по программе от одной точки останова к другой и при каждой остановке выполнения просматривать критичные переменные, а по мере необходимости и изменять их значения. Если точек останова нет, запуск отладчика таким способом приведет к выполнению всей программы без остановок. Конечно факт запуска отладки подобным образом не означает, что вы обязаны продолжать ее в такой же манере при каждой остановке выполнения можно выбрать любой из доступных вариантов перемещения по коду.
  2. Пунк Attach to Process (Присоединиться к процессу) меню Debug позволяет отлаживать программу, которая уже запущена. Это средство отображает список процессов, работающих на машине, в котором можно выбрать процесс, требующий отладки. Это инструмент для опытных пользователей, и лучше избегать экспериментов с ним, если только вы не уверены в том, что собираетесь делать. Можно очень легко заблокировать машину или вызвать другие проблемы, если вмешаться в критические процессы операционной системы.
  3. Пункт меню Step Into (Войти), также доступный как кнопка панели инструментов Debug, выполняет программу по одному оператору за раз, входя в каждый блок кода, включая каждую вызываемую функцию. Это может оказаться весьма утомительным, если использовать такой режим отладки на протяжении всего процесса, поскольку при этом, например, будет выполняться весь код библиотечных функций, что вряд ли вас заинтересует, если только вы не заняты их разработкой. Небольшое количество библиотечных функций написано на языке ассемблер, включая некоторые из тех, которые поддерживают потоковый ввод вывод. Функции на языке ассемблер выполняются по одной машинной инструкции за раз, что как и можно ожидать, занимает значительное время.
  4. Пункт Step Over (Перешагнуть), также доступный в виде кнопки панели инструментов Debug, выполняет операторы программы по одному за раз и выполняет весь код функций, которые могут быть вызваны в операторе, без остановок.

Имеется и пятая возможность для запуска в режиме отладки, который не появляется в меню Debug. Щелкните правой кнопкой мыши на любой строке кода и выберите из контекстного меню пункт Run to Cursor (Выполнить до курсора). Произойдет именно то что гласит этот пункт, – программа будет запущена до строки, в которой находится курсор, а затем ее выполнение будет прервано, что позволит вам просмотреть или изменить значения переменных программы.

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

Дальше просто ставите точки останова в коде, запускаете отладку любым из пяти способов, и затем смотрите необходимые значения переменных в меню Отладка=>Окна

QIP Shot - Screen 138Как видно из рисунка выше можно посмотреть локальные и видимые переменные, а также их изменить. Что бы посмотреть локальные переменные выберите пункт Локальные.

QIP Shot - Screen 139Вы их можете менять наведя на значение переменной и нажав два раза клавишей мышки

Так же можно посмотреть значение переменной наведя курсор мышки на эту переменную

QIP Shot - Screen 140Так же можно посмотреть стек вызовов в окне Стек вызовов

QIP Shot - Screen 141Во вкладке Отладка=>Окна=>Контрольные значения можно задавать переменные которые нужно отслеживать

QIP Shot - Screen 142

появится окно в котором нужно ввести имя переменной или нескольких переменных.QIP Shot - Screen 143Добавление отладочного кода

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

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

Первый способ, с помощью которого можно проверить поведение программы, обеспечивается библиотечной функцией С++

Использование Утверждений

Файл заголовка стандартной библиотеки cassert объявляет функцию assert(), которую можно использовать для проверки логических условий в программе, когда не определен специальный символ препроцессора NDEBUG. Эта функция объявлена следующим образом

void assert(int expression);

Аргумент функции задает условие, которое должно быть проверено, но эффект от функции assert() подавляется, если определен специальный символ препроцессора  NDEBUG. Символ NDEBUG автоматически определяется в рабочей версии программы, но не в отладочной версии. Поэтому утверждение (assertion) проверяет свой аргумент в отладочной версии программы, но ничего не делает в рабочей версии. Если хотите отключить этот механизм в отладочной версии программы, определите символ NDEBUG явно, используя директиву #define. Чтобы это возымело действие, такую директиву необходимо поместить раньше директивы #include для заголовочного файла cassert в исходном файле.

#define NDEBUG //Отключить механизм утверждений в коде
#include <cassert>//Объявление assert()

Если выражение, переданное в качестве аргумента функции assert(), возвращает не нуль (т.е. значение true), функция ничего не делает. Но если выражение равно нулю (другими словами, значение false) и символ NDEBUG не определен, выводится диагностическое сообщение, показывающее выражение, которое вернуло значение false, имя файла исходного кода и номер строки в исходном файле, где это произошло. После отображения диагностического сообщения функция assert() вызывает функцию abort() для завершения программы.

Рассмотрим реальный примерчик кода

#include <iostream>
using std::cout;
using std::endl;

//при раскомментировании assert игнорируется
//#define NDEBUG 
#include <cassert>

int main()
{
	int a=4;
	int b=5;

	//проверить что а > b
	assert(a>b);

	return 0;
}

вывод:

QIP Shot - Screen 144как видно сработал assert, что означает ошибка отладки. В коде выше мы проверяем что б а было всегда больше b, если а меньше b, то вызывается assert() оно выводит окошко с тремя кнопками. Щелчок на кнопке Abort (Прервать) немедленно завершает программу. Кнопка Retry (Повторить) запускает отладчик среды разработки Visual C++ 2010, так что можете пошагово выполнить программу, чтобы подробнее выяснить причину отказа утверждения. В принципе кнопка Ignore (Игнорировать) позволяет продолжить выполнение программы, несмотря на ошибку, но обычно это неразумный выбор, поскольку результат, скорее всего, будет непредсказуемым.

В качестве аргумента функции assert() можно использовать логические выражение любого рода. Можно сравнивать значения, проверять указатели, верифицировать типы объектов или выполнять любую другую полезную проверку, чтобы убедиться в корректности работы вашего кода

Например проверить указатель

assert(ptr!=0);

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

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

Добавление собственного отладочного кода

Используя директивы препроцессора, вы сможете добавить любой код, который ходите, к своей программе – так, чтобы он компилировался и выполнялся только в ее отладочной версии. Отладочный код полностью исключается из рабочей версии, потому он вообще не влияет на эффективность проверенной программы. Отсутствие символа NDEBUG, может служить управляющим механизмом для включения отладочного кода, т.е. символ, используемый для управления функцией assert() стандартной библиотеки, о которой упоминалось выше, может послужить и вашему отладочному кода. В качестве альтернативы для лучшего и более позитивного управляющего механизма можно применять другой символ препроцессора – _DEBUG, который всегда автоматически определяется средой разработки Visual C++ в отладочной версии программы, но который должен компилировать и выполняться только во время отладки,  между парой директив препроцессора – #ifdef и #endif, проверяя наличие символа _DEBUG, как покажано ниже.

#ifndef _DEBUG    //Код для отладки...
#endif //_DEBUG

Код между директивами препроцессора #ifdef и #endif компилируется, только если определен символ _DEBUG. Это значит что когда ваша программа будет полностью проверена, вы сможете собрать рабочую версию, полностью свободную от накладных расходов, связанных с отладочным кодом (в рабочей версии макрос _DEBUG в visual C++ не определен).

В программах можно определять несколько отладочных переменных например так

#ifdef _DEBUG

#define DEB1
#define DEB2

#endif

и вставлять добавочный код например так

#ifdef DEB1
//добавляем код отладки
#endif

и для DEB2 так же

#ifdef DEB2
//код отладки
#endif

Вы можете закомментировать #define DEB1 и у вас будет вставляться отладочный код только для DEB2, теперь вы можете создавать сколько хотите видов отладочного кода.

Пример отладочного кода:

Показать »

#include <iostream>
using std::cout;
using std::endl;
#include <cstring>
#include <cassert>

#ifdef _DEBUG

#define TRACE_F
#define VAR_F

#endif

class a
{
	char* str;
public:
	void setStr(const char* p)
	{
		//использование утверждения
		assert(p!=0); 

#ifdef TRACE_F
		cout <<"begin setSTr"<<endl;
#endif

#ifdef VAR_F
		cout <<"p= "<<p<<endl;
#endif

		str=new char[strlen(p)+1];
		strcpy(str,p);

#ifdef TRACE_F
		cout <<"end setSTr"<<endl;
#endif
	}

};

int main()
{
	a obj;
	obj.setStr("hellow world");

	//вызовет assert();
/*	char* p=nullptr;
	obj.setStr(p);//вызовет утверждение
*/
	return 0;
}

вывод:

QIP Shot - Screen 145

в коде выше можно закомментировать один из макросов например

//#define VAR_F

и у нас получится уже другой вывод:

QIP Shot - Screen 146

 

Отладка программы

И так как же все таки отлаживать программы? Я честно сам отладчиком не пользуюсь, а сам пытаюсь делать вывод поэтапно использую cout и exit, но сейчас подчитав литературу понял что можно и так отлаживать программы, даже наверно так будет и проще, можно сразу в реале смотреть значения переменных.

Нет реально так пошагово выполняя операторы мы сможем выявлять не все ошибки, а только ошибки которые сразу вылезут. Ну от щас на пример просто посмотрим как это делается. Мы сейчас пройдем код нашей программы выше пошагово используя клавиши <F10> и <F11>

QIP Shot - Screen 147

Нажимаем <F10> и мы попадаем в следующее окноQIP Shot - Screen 148Стрелочка показывает где мы находимя, следующим будет выполнятся оператор a.obj; – создание объекта. В самом низу Локальные будут отображаться переменные, так же мы можем открыть окно стека вызовов в меню Отладка=>Окна=>Стек вызовов. Нажимаем еще раз <F10>QIP Shot - Screen 149на изображении выше видно, что у нас создался объект типа a obj; и видно в окне Локальные, что указатель str находится по адресу 0xcccccccccc неправильный. Ну это пока еще не важно. Следующий будет выполнен оператор obj.setStr(“hellow world”); ,мы можем зайти в эту функцию setStr() используя клавишу <F11> обход с заходом и дальше уже используя клавишу <F10> пройти пошагово без захода каждый оператор функции setStr, что мы и сделаем. Нажмите клавишу <F11> QIP Shot - Screen 151и мы попадаем в функцию setStr() в ее начало. Теперь мы можем пройти эту функцию пошагово каждый оператор используя клавишу <F10> или с заходом в функции используя клавишу <F11>

Например лично я не знал, что в отладчике visual C++ 2010 можно заходить в функции и их проходить пошагово используя клавиши <F10> и <F11>, честно до написания этой статьи не знал, а все вручную свой код отлаживал, да и привык уже в ручную все отлаживать, теперь буду пробовать с отладчиком.

Ну и дальше нажимая клавиши <F10> мы обойдем пошагово каждый оператор до конца функции. QIP Shot - Screen 152Мы просто прошли всю функцию от и до и на рисунку видно что у нас указатель str стал указывать на “hellow wlrd” то есть мы инициализировали объект this этой строкой. Зайдем в “стек вызовов” QIP Shot - Screen 153и у нас откроется окошкоQIP Shot - Screen 154Из которого видно что мы находимся в функции QIP Shot - Screen 155нажимаем дальше клавишу <F10> два раза QIP Shot - Screen 156и мы выходим из функции и следующий будет выполнен оператор return 0; – это конец программы. Так же мы видим что у нас переменная obj хранит правильный указатель str инициализированный строкой “hellow world”.

В общем можно сказать что мы с помощью отладчика visual C++ 2010 можем легко посмотреть внутренности программы от и до, просто мы можем обойти всю программу шаг за шагом и смотреть как изменяются переменные. В принципе это можно сказать хорошая штука. Можно конечно это все делать вручную.

Да ребятки так же мы можем выходить из функции используя комбинацию клавиш <Shift+F11>, а заходим с помощью <F11>.

Реально я только что подсмотрел в меню, там появился пункт “Шаг с выходом”.

Для окончания отладки нажмите клавишу <F5>.

Ну и пожалуй на этом с отладкой все.

 

Функции проверки динамической памяти

 Здесь приводится обзор средств, позволяющих проверить операции с динамической памятью и обнаружить ее утечки. Функции, объявленные в файле заголовка crtdbg.h, проверяют динамическую память, используя записи о его состоянии, которые хранятся в структуре типа _CrtMemState.

Эта структура относительно проста и определена следующим образом.

typedef struct _CrtMemState
{
	struct _CrtMemBlockHeader* pBlockHeader;//Указатель на последний
											//выделенный блок
	unsigned long lCounts[_MAX_BLOCKS];//Количество блоков каждого типа
	unsigned long lSizes[_MAX_BLOCKS];//Общее количество байт,
										//выделенных для каждого типа
										//блоков
	unsigned long lHighWaterCount;		//Максимальное количество байт,
										//выделенных одновременно
										//до настоящего момента
	unsigned long lTotalCount;			//Общее количество байт
										//выделенных на настоящий момен
} _CrtMemState;

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

  • Запись состояния динамической памяти в любой точке.
  • Определение разницы между двумя состояниями динамической памяти.
  • Вывод информации о состоянии.
  • Вывод информации об объектах в динамической памяти.
  • Обнаружение утечек памяти.

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

void _CrtMemCheckpoint(_CrtMemState* state);

Эта функция сохраняет текущее состояние динамической памяти в структуре _CrtMemState. Аргумент, передаваемый функции, – это указатель на структуру _CrtMemState, в которую записывается информация состояния.

 

int _CrtMemDifference(_CrtMemState* stateDiff,
                               const _CrtMemState* oldState,
                               const _CrtMemState* newState);

Эта функция сравнивает состояние, указанное третьим аргументом, с предыдущим состоянием, указанным во втором аргументе. Разница сохраняется в структуре _CrtMemState, которая передается в первом аргументе. Если состояния отличаются, функция возвращает ненулевое значение (true), в противном случае возвращается нуль (значение false).

 

void _CrtMemDumpStatisties(const _CrtMemState* state);

Это сбрасывает информацию о состоянии динамической памяти, указанную аргументом, в выходной поток. Структура состояния, на которую указывает аргумент, может быть состоянием, записанным функцией _CrtMemCheckpoint(), или разницей между двумя состояниями, произведенной функцией _CrtMemDifference().

 

void _CrtMemDumpAllObjectsSince(const _CrtMemState* state);

Функция сбрасывает информацию об объектах, размещенных в динамической памяти с момента состояния динамической памяти, указанного в о

 

Нет я не хочу их перечислять это большая темя, мы просто рассмотрим примерчик кода который мы использовали выше и добавим в него дополнительный код

Показать »

#include <iostream>
using std::cout;
using std::endl;
using std::cin;
#include <cstring>
#include <cassert>

#include <crtdbg.h>

#ifdef _DEBUG

#define TRACE_F
#define VAR_F

#endif

class a
{
    char* str;
public:
    void setStr(const char* p)
    {
        //использование утверждения
        assert(p!=0);

#ifdef TRACE_F
        cout <<"begin setSTr"<<endl;
#endif

#ifdef VAR_F
        cout <<"p= "<<p<<endl;
#endif

        str=new char[strlen(p)+1];
        strcpy(str,p);

#ifdef TRACE_F
        cout <<"end setSTr"<<endl;
#endif
    }

};

int main()
{
	//Включить отладку динамической памяти и проверку утечек памяти
	_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);

	//Направить предупреждение в cout
	_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
	_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);

    a obj;
    obj.setStr("hellow world");

    //вызовет assert();
/*  char* p=nullptr;
    obj.setStr(p);//вызовет утверждение
*/
    return 0;
}

вывод:

QIP Shot - Screen 157

Мы видим что у нас Detected memory leaks! Видно что у нас существует утечка. Почему такое произошло? А все просто мы выделили динамически память с помощью оператора new, но забыли ее удалить с помощью оператора delete[]. Добавьте в класс а деструктор

~a(){if(str!=nullptr)delete[] str;}

и у вас будет вывод уже без утечек памяти

QIP Shot - Screen 145На этом с динамической памятью все. Если нужно будет глубже разбираться читайте специализированную литературу.

И так господа мы разобрали более менее отладку, но эта тема довольно сложная и обширная, ошибки в программе не всегда стандартными средствами или с помощью отладчика исправишь. Если вы пишете программу например какой нит “синтаксический анализатор html” то там вам заранее неизвестны данные, и бывают ни с того ни с чего ошибки вылазят, они как правило симантические потому что программа начинает делать не то что должна она делать.

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

Ну ладно ребятки на этом пожалуй все, буду пробовать сам использовать отладчик visual C++ мб будет получаться, но все таки я склоняюсь к ручному исправлению ошибок и собственному написанию отладочного кода, для меня это привычнее.

Кстати это не весь арсенал средств  visual C++ для отладки. Полное описание средств смотрите в справке visual C++ 2010, Отладка.  Visual C++ предоставляет большое количество средств для отладки.

[youtube]https://www.youtube.com/watch?v=usL27PV9h70[/youtube]

Комментарии:


Оставить комментарий

Your email address will not be published. Required fields are marked *