C++ — Ошибка в программе


Содержание

Microsoft Visual C++ Runtime Library

Ошибка Microsoft Visual C++ Runtime Library Error возникает при запуске программ и игр на ОС Windows самых разных версий. Однозначно сказать, что приводит к появлению неполадки, невозможно. Пакет Microsoft Visual C++ является сложной интегрированной системой, поэтому рассмотрим все варианты решений, накопленные опытным путем. Каждый метод помогает в определенных случаях, и есть продуктом синтеза знаний и опыта, которые были структурированы и переработаны в статью. Цель ее – дать инструкции по исправлению ошибки. Мы надеемся, что информация принесет пользу и поможет решить вашу проблему.

Причины возникновения ошибки

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

1. Запуск от имени администратора и в режиме совместимости

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

  1. Правой кнопкой мыши на ярлык с игрой.
  2. Кликнуть на строчку, показанную на скриншоте.
  3. Подтвердить действие.
  4. Дождаться запуска.
  1. Правой кнопкой на ярлык приложения.
  2. Клик на строчку «Свойства».
  3. В окне выбрать раздел «Совместимость».
  4. Поставить галочку, как на картинке.
  5. В строке выбора ОС указать вашу текущую версию.
  6. Нажать «Применить» и «ОК».
  7. Запустить приложение.

2. Ошибка из-за некорректного имени учетной записи

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

  • «Панель управления».
  • «Учетные записи и Семейная безопасность».
  • «Учетные записи пользователей».
  • «Управление другой учетной записью».
  • В новой вкладке окна добавляем нового пользователя с именем на английском языке.
  • Перейти в новую учетную запись.
  • Запустить приложение.

Иногда помогает переименовать каталог с кириллицы на латынь. Например с C:\Игры на C:\Games

3. Переустановка приложения (игры, программы)

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

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

  • Зайти в «Пуск».
  • «Панель управления».
  • «Программы и компоненты».
  • Найти и удалить проблемное приложение.
  • Скачать его из другого источника.
  • Установить.
  • Запустить.

4. Переустановка Microsoft Visual C++

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

Дефект устраняется при помощи обновления и переустановки программного комплекса. Предпочтительнее полностью переустановить Visual C++. Перед этим следует удалить все установленные пакеты. Для этого зайти в «Программы и компоненты» и далее по списку:

  • Найти Microsoft Visual C++.
  • Удалить.
  • Скачать Microsoft Visual C++, исходя из разрядности вашей операционной системы (х86 для 32-разрядной, х64 для 64-разрядной);
  • Установить;
  • Перезагрузить компьютер;
  • Запустить проблемное приложение;

5. Переустановка net. Framework

Он также исполняет особую роль при запуске, поэтому проделаем те же действия, что и с Visual C++. Удалению, скачиванию и установке теперь подлежит net. Framework


6. Переустановка DirectX

Наравне с вышеуказанными платформами программа также участвует в запуске и работе приложений. Переустановка решит проблему, если она заключена в ней.

  • Скачать DirectX
  • Установить и перезагрузиться.
  • Запустить неработающее приложение.

7. Драйвера на видеокарту

Устаревшая версия драйвера на видеокарту или ошибки, которые иногда возникают в работе драйверов, могут приводить к последствиям в виде ошибок. Рекомендуется удалить драйвера через «Программы и компоненты» и повторно скачать, установить свежую версию с сайта производителя видеокарты. Далее, выполнить перезагрузку и запуск приложения, с которым связаны проблемы.

8. Неверно выставленное время

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

Как исправить ошибку на Windows 10

Способ работает исключительно на Виндовс 10, поэтому рассматриваем его отдельно от остальных. Суть в том, что эта версия ОС может запрещать автоматическое обновление некоторых служб, в частности Visual C++ и net.Framework. После включения этой возможности, Windows обновит эти программы и после перезагрузки следует повторить запуск. Порядок действий:

  1. Программы и компоненты.
  2. Включение и отключение компонентов Windows.
  3. В окне поставить галочки напротив служб, где стоит черный квадрат, как на картинке.
  4. Подождать окончания автообновления.
  5. Перезагрузиться.
  6. Запустить приложение.

Заключение

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

Если у Вас остались вопросы, можете задавать их в форме комментариев чуть ниже

Вывод ошибок на экран в С++

можно ли в С++ вывести на экран ошибки в программе? если да, то можете привести маленький пример кода? Если будет с объяснениями, то вдвойне буду благодарен.

2 ответа 2

Есть такая штука, как GCC. Но большинство современных компиляторов используют её на автомате, то есть ошибки выводятся в определенные лог-лист(как в Dev-CPP). Она выявляет логические ошибки в программном коде, поддерживает великое множество всяких спецификаторов(например, если надо искать только ошибки, связанные с неправильным выделением памяти и т.д). Для C++ я бы рекомендовал использовать следующие набор спецификаторов:

-Wctor-dtor-privacy -Weffc++ -Wold-style-cast -Woverloader-virtual

Применять спецификаторы необходимо именно на этапе компиляции.

Пояснения к некоторым спецификаторам:

// -Weffc++ — предупреждает о ряде нарушений из книг Скотта Мейерса «Effective C++». Например, к ним относятся виртуфльные деструкторы для базовых классов, а также опредедения копирующих конструкторов для классов с членами-указателями

Дополнение:

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

Где «try» — попытка выполнить какой-л. код, «throw» — генерация исключительной ситуации, если возникла ошибка в блоке «try». И «catch» — обработка сгенерированной ситуации(можно вывести ошибку, например)


Обработка ошибок: Защитное программирование

Введение

В любой программе, сложнее чем «Hello, world» , неизбежно будут происходить ошибки и различные сбои. Поэтому если вы хотите писать надежный и стабильный код, то обязаны заботиться обо всем этом. Конечно, в большинстве случаев нет смысла становиться параноиком и проверять абсолютно все. С другой стороны, во многом это зависит от области применения приложения, которое вы разрабатываете. Если это система контроля банковских переводов или управления полетом спутника, то единственная ошибка в коде может обойтись очень дорого. В этом случае вам на помощь приходит «защитное программирование». Одно из лучших описаний этой методики, на мой взгляд, приводится в следующих книгах:

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

Примеры кода я буду приводить на C++, однако это не должно стать для вас серьезной помехой, если вы пишите на Java, C# или каком-нибудь другом языке со схожим синтаксисом, поскольку многие техники обработки ошибок являются универсальными.

Реклама

Коды ошибок

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

Двойная ответственность

Вот как может выглядеть подобная функция:

Но как мы узнаем, удалась ли регистрация или нет? Первый подход основывается на предположении, что идентификатор пользователя должен быть неотрицательным числом. Таким образом, в случае ошибки функция registerUser() может возвращать отрицательное значение, например, -1 . Тогда код взаимодействия с функцией регистрации может выглядеть следующим образом:

Такой способ применяется довольно часто, но он имеет некоторые очевидные недостатки. Например, когда мы инициализируем переменную userID значением, которое возвращает функция registerUser() , то на самом деле мы врем. Ведь эта переменная хранит идентификатор пользователя ИЛИ код ошибки, то есть должна называться userIDOrErrorCode . Имя получилось длинным и пользоваться им будет неудобно. Но сразу становится понятно, что эта переменная имеет два назначения (выглядит подозрительно, не правда ли?). Однако даже это не является главным недостатком. В какой-то момент требования к типу идентификатора могут измениться. Например, мы можем решить, что лучше использовать беззнаковое целое число:

Обратите внимание, что в первую очередь я добавил определение typedef для типа UserID . Теперь мы сможем менять фактический тип идентификатора всего в одной строке. Для сравнения, когда мы явно пользовались типом int , то в зависимости от объема кода подобная тривиальная операция могла бы занять несколько часов. Поэтому старайтесь не повторяться (см. Принцип DRY в действии).

Кроме того, теперь мы явно указываем, что функция registerUser() возвращает именно идентификатор UserID , а не идентификатор ИЛИ код ошибки. Иначе мы вновь обманываем тех, кто будет вызывать нашу функцию.

Указатель для ошибки

Итак, логику мы подправили, но как теперь сообщить о произошедшей ошибке? Один из часто применяемых подходов заключается в том, чтобы вернуть информацию об ошибке через дополнительный параметр. Например:

Цукерберг рекомендует:  Диагональное портфолио с вращением изображений

Этой функцией мы можем пользоваться следующим образом:

Выглядит неплохо. Но у вас мог возникнуть вопрос: «А какое значение будет у переменной userID , если ok == false «? Можно предположить, что это будет 0 , то есть функция registerUser() должна вернуть некое нейтральное значение. Например, в случае, когда ожидается возврат класса или структуры, это может быть Null -объект или объект с функцией-членом на подобии isValid() , которая возвращает false , если экземпляр класса находится в некорректном состоянии. Кстати, если бы registerUser() была не обычной функцией, а являлась членом класса, то мы бы могли вообще не возвращать никаких признаков ошибки, но добавить в сам класс что-то вроде getLastError() .

Вот это поворот

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

Мы поменяли местами идентификатор и переменную с информацией об успешности выполнения регистрации. Пользоваться этой функцией можно следующим образом:

Однако, как вы можете видеть, принципиально ничего не изменилось. Нам все равно приходится инициализировать идентификатор userID значением по умолчанию, но теперь это происходит не в самой функции, а до ее вызова. Если мы не хотим, чтобы переменная userID имела смысл без явной инициализации (хотя всегда есть возможность добавить в иерархию классов Null -объект), то можно воспользоваться альтернативным решением:

На этот раз registerUser() принимает не просто указатель на UserID , а двойной указатель. То есть память для идентификатора пользователя выделяется внутри функции registerUser() . А чтобы быть последовательными, освобождать память для userID мы будем не оператором delete , а с помощью функции releaseMemory() , которую сами должны предусмотреть.

Подобным образом часто пишутся C-библиотеки, которые представляют собой обертку над ООП-кодом на C++. Это делается для получения высокой совместимости библиотек, что особенно актуально для Windows. Вы не можете подключить библиотеку на C++ к проекту, если версии компиляторов, с которой работаете вы, и с которой была собрана библиотека, отличаются. Поэтому если вы хотите сохранить реализацию своей библиотеки закрытой, то оказываетесь ограничены использованием низкоуровневых типов данных, которые есть в C. Но чтобы не отбрасывать свои наработки и не переписывать весь код заново на чистом C, используется показанная выше методика. При этом в пользовательском коде вся работа ведется не с самими экземплярами классов, а с указателями на них. А для выделения и освобождения памяти используются специально предусмотренные функции, которые предоставляет библиотека. Более того, определений классов в заголовочных файлах библиотеки нет вовсе (для простоты я сделал допущение, что мы можем создать экземпляр класса User , хотя его тоже не было бы). Вам доступно лишь объявление, которого достаточно для определения указателя на класс. Из-за этого все вызовы функций-членов должны осуществляться также с помощью C-функций, которые ожидают получить указатель на объект, а входные и выходные аргументы должны быть представлены с помощью примитивных типов, на подобии int или char . Впрочем, это было небольшое отступление от нашей темы. Однако если у вас есть желание узнать об этом вопросе поподробнее, то пишите свои пожелания в комментариях и я подготовлю соответствующую полноценную заметку.

Кто там?

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

Чтобы избежать проблем с областью видимости при объявлении перечисления ResultCode , мы создали пространство имен RegistrationLib . Использование namespace -ов вообще является хорошей практикой при написании кода, который вы планируете кому-то передавать. Теперь registerUser() не просто говорит о том, что что-то случилось, но и указывает причину. Конечно, в качестве примера я взял простейший набор возможных типов ошибок, которые могли бы случиться. К тому же, они не так детальны, как хотелось бы. Проблем с заполнением структуры User может быть немало, а уж при работе с базами еще больше. Однако я думаю, что суть вы уловили.


Чуть выше

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

Допустим, мы хотим реализовать высокоуровневую функцию, в которой сначала получаем данные пользователя, затем пробуем провести его регистрацию (с помощью нашей функции registerUser() ), а в конце отправляем идентификатор нового пользователя на удаленный сервер, если регистрация удалась. Сначала рассмотрим самый линейный вариант:

Я думаю, у вас не вызовет трудностей разобраться с представленным кодом. В целом он основывается на тех принципах, которые мы уже обсудили выше. Но логика работы функции onUserDataReady() выглядит довольно запутанной. Таковой она и является. Это связано с тем, что мы использовали множество вложенных условных конструкций, что осложняет чтение кода. Несколько улучшить ситуацию нам поможет следующий прием:

Получившийся код выглядит несколько проще. Это достигается за счет уменьшения вложенности проверок. Однако обратите внимание, что перед вызовом registerUser() и sendUserIDToRemoteServer() нам приходится проверять результат выполнения предыдущих действий. Такая необходимость появляется по той причине, что если на n -ом шаге что-то случилось, то все оставшиеся шаги уже не имеют смысла. Фактически после ошибки на каком-то из шагов функция onUserDataReady() должна завершаться. Для этого мы бы могли попробовать сделать что-то подобное:

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

Обычно goto не рекомендуют применять. И это вполне оправдано. Ведь при неумелом использовании код быстро становится хаотичным и запутанным (спагетти-код). Но если вы знаете, что делаете, то почему бы нет? Представленный выше фрагмент программы является хорошим примером, что из каждого правила есть исключения.

Однако есть еще более надежный и качественный вариант. Он заключается в использовании принципа RAII. Наиболее известным примером реализации этого механизма является Умный указатель. Более подробно об этой идиоме я расскажу во второй части, а сейчас посмотрим, как будет выглядеть код функции onUserDataReady() на основе RAII в нашем случае:

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

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

Реклама

Заключение

Наше знакомство с базовыми принципами обработки ошибок закончено. Мы успели рассмотреть основные способы возврата кодов ошибок; коротко вспомнили принцип создания C-оберток над ООП кодом C++ для создания переносимых библиотек; а также разобрались с возможными вариантами реализации функции-обработчика, которая должна проверять коды ошибок. Встретимся во второй части.

C++ — Ошибка в программе

Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда — alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Форум программистов > Технологии > Помощь студентам
[C++] ошибка в коде программы!!
Регистрация
Поиск по форуму
Расширенный поиск
К странице.
Страница 1 из 2 1 2 Следующая >

Помогите пожалуйста!! вот смотрите есть код он как бы почти правильный только он подсчитывает неправильно
Пример надо вводить
0
0
2
-5
5
1

Он должен выводить 1.666

как этого добится помогите,очень вас прошу!! вот сам код

#include
#include
void main (void)
<
float x,a,b,c,f,xk,dx,xn;
cin >> a >> b >> c >> xn >> xk >>dx;
for (x=xn;x 0 && b==0) f=x-a/x-c;
else if (f=x/c);
cout

Ошибка Microsoft Visual C++ Runtime Library. Как исправить?

Не так давно помогал одному хорошему знакомому с настройкой компьютера: у него при запуске любой игры выскакивала ошибка Microsoft Visual C++ Runtime Library… Так собственно и родилась тема этого поста: опишу в нем подробные шаги по восстановлению работоспособности ОС Windows и избавлению от этой ошибки.


Вообще, ошибка Microsoft Visual C++ Runtime Library может появиться по многим причинам и разобраться, порой, не так просто и быстро.

Типичный пример ошибки Microsoft Visual C++ Runtime Library.

1) Установка, обновление Microsoft Visual C++

Многие игры и программы были написаны в среде Microsoft Visual C++. Естественно, если у вас нет этого пакета, то игры работать не будут. Чтобы это исправить, нужно установить пакет Microsoft Visual C++ (кстати, распространяется бесплатно).

Ссылки на офиц. сайт Microsoft:

2) Проверка игры/приложения

Вторым шагом по устранению ошибок запуска приложений и игр — станет проверка и переустановка самих этих приложений. Дело в том, что возможно у вас были испорчены какие-нибудь системные файлы игры (dll, exe файлы). Причем, испортить могли как вы сами (случайно), так и например, «зловредные» программы: вирусы, трояны, рекламное ПО и пр. Часто банальная переустановка игры полностью избавляла от всех ошибок.

3) Проверка компьютера на вирусы

Многие пользователи ошибочно думают, что раз установлен какой-нибудь антивирус — значит никаких вирусных программ у них нет. На самом деле даже какое-нибудь рекламное ПО способно нанести определенный вред: замедлить работу компьютера, привести к появлению всевозможных ошибок.

Рекомендую проверить компьютер несколькими антивирусами, кроме этого ознакомиться с этими материалами:

4) NET Framework

NET Framework — программная платформа, на которой разрабатывают различные программы и приложения. Чтобы эти приложения могли запуститься, у вас на компьютере должна быть установлена требуемая версия NET Framework.

Все версии NET Framework + описание.

5) DirectX

Самая распространенная (по моим личным подсчетам) из-за чего происходит ошибка Runtime Library — это «самопальные» установки DirectX. Например, многие устанавливают на Windows XP 10-ю версию DirectX (в рунете на многих сайтах есть такая версия). Но официально XP не поддерживает 10-ю версию. В результате начинают сыпаться ошибки…

Рекомендую удалить через диспетчер задач (Пуск/панель управления/установка и удаления программ) DirectX 10, а затем произвести обновление DirectX через рекомендованный установщик от Microsoft (более подробно о вопросах с DirectX — см. в этой статье).

6) Драйвера на видеокарту

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

1) Рекомендую проверить официальный сайт вашего производителя и скачать последнюю версию драйвера.

2) Затем удалить полностью старые драйвера из ОС, и установить новые.

3) Попробовать снова запустить «проблемную» игру/приложение.

PS

1) Некоторые пользователи заметили одну «незакономерную закономерность» — если у вас время и дата в компьютере не правильные (передвинуты сильно на будущее), то ошибка Microsoft Visual C++ Runtime Library может появляться и из-за этого. Дело в том, что разработчики программ ограничивают их срок использования, и, естественно, программы проверяя дату (видя что наступил крайний срок «X») — прекращают свою работу…

Исправить очень просто: установить реальную дату и время.

Исключения в С++

Иногда, во время работы программ, встречаются ситуации которые препятствуют дальнейшей нормальной их работе. К примеру при делении числа на ноль, программа завершит работу не смотря на то, сколько пользователь работал в программе, и какой объем данных внес. Программа просто закроется.


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

Такого рода ситуации программистам надо стараться предвидеть и строить программы так, чтобы они могли гибко реагировать, а не аварийно закрываться. В моей любимой книге Язык программирования C++. Лекции и упражнения автора С. Прата, дано следующее определение исключениям в С++:

Чтобы вам не сложно было понять механизм работы исключений в С++, рассмотрим их на простом примере. В нем мы предвидим тот случай, что в какой-то момент в ходе расчетов программы, может встретиться деление числа на 0. Наберите и скомпилируйте код, расположенный ниже. Чтобы убедиться в том, как реагирует программа на такую ситуацию, внесите число 0 в переменную num2 (она выступает делителем в примере).

Исключения

Обработка исключений

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

Например, в следующей программе происходит деление чисел:

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

С одной стороны, мы можем в функции divide определить проверку и выполнять деление, если параметр b не равен 0. Однако нам в любом случае надо возвращать из функции divide некоторый результат — некоторое число. То есть мы не можем просто написать:

И в этом случае нам надо известить систему о возникшей ошибке. Для этого используется оператор throw .

Оператор throw генерирует исключение. Через оператор throw можно передать информацию об ошибке. Например, функция divide могла бы выглядеть следующим образом:

То есть если параметр b равен 0, то генерируем исключение.

Но это исключение еще надо обработать в коде, где будет вызываться функция div >try. catch . Она имеет следующую форму:

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

После ключевого слова catch в скобках идет параметр, который передает информацию об исключении. Затем в блоке производится собственно обработка исключения.

Так изменим весь код следующим образом:

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

В блоке catch идет обработка исключения. Причем многоточие в скобках после оператора catch ( catch(. ) ) позволяет обработать любое исключение.

В итоге когда выполнение программы дойдет до строки double z = divide(x, y); , будет сгенерировано исключение, поэтому последующие инструкции из блока try выполняться не будут, а управление перейдет в блок catch, в котором на консоль просто выводится сообщение об ошибке. После выполнения блока catch программа аварийно не завершится, а продолжит свою работу, выполняя операторы после бллока catch:

Чтобы скомпилировать данный пример с конструкцией try. catch с помощью g++ может потребоваться использование флага -static :

Однако в данном случае мы только знаем, что произошла какая-то ошибка, а какая именно, неизвестно. Поэтому в выражении catch мы можем получить то сообщение, которое передается оператору throw:

С помощью параметра const char* msg получаем сообщение, которое предано оператору throw, и выводит это сообщение на консоль. И в этом случае консольный вывод будет выглядеть следующим образом:

Таким образом, мы можем узнать суть возникшего исключения.

Ошибка Microsoft Visual C++ Runtime Library и её исправление

Описание ошибки

Некоторые пользователи в процессе работы с какими-то программами или играми могут столкнуться со следующей ошибкой:

Microsoft Visual C++ Runtime Library
Runtime error!


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

Отсутствие в системе нужных файлов Microsoft Visual C++

Одной из распространенных причин по появлению подобной ошибки может стать отсутствие нужных библиотек от Microsoft Visual C++. Для того, чтобы их установить, нужно скачать специальный набор этих библиотек, которые именуются как «Распространяемый пакет Microsoft Visual C++».

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

Установка Microsoft .NET Framework

Кроме библиотек Microsoft Visual C++ программа может нуждаться в определенной версии Microsoft .NET Framework. Не лишним будет скачать и установить хотя бы версии .NET Framework 3.5 и 4:

Обновление версии DirectX

Так же не лишним будет обновить версию DirectX до последней. Если у вас Windows XP, и вы установили некий «DirectX 10 для Windows XP» — немедленно удалите. Скачать последнюю версию Microsoft DirectX можно по этой ссылке .

Поврежденные файлы программы

Еще часто может быть, что поврежденны файлы самой программы или игры, поэтому не лишним будет попробовать переустановить её. Что касается игр, то многие сервисы цифровой дистрибюции (Steam и другие) имеют функцию проверки файлов игры на повреждения.

Проверка компьютера на вирусы

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

VivaMP, система выявления ошибок в коде параллельных программ на языке С++, использующих OpenMP

Поддержка OpenMP была прекращена в PVS-Studio после версии 5.20. По всем возникшим вопросам вы можете обратиться в нашу поддержку.

В настоящее время программные продукты Viva64 и VivaMP включены в состав PVS-Studio и более не распространяются как отдельные приложения. Используйте программу PVS-Studio для получения необходимых возможностей проверки кода.

Аннотация

В статье приводятся результаты исследований ошибок, которые допускают программисты, использующие С++ и OpenMP. Для автоматического обнаружения этих ошибок предлагается использование статического анализа. Описывается интегрирующийся в среду Visual Studio анализатор VivaMP, реализующий поставленную задачу.

1. Введение

По оценкам компании Evans Data, проводящей опросы среди разработчиков ПО, общее количество программистов в мире к 2009 году составит 17 миллионов человек[1]. На сегодняшний день 40% из них используют язык С++, причем около 70% разработчиков занимаются разработкой многопоточных приложений сейчас или планируют начать ее в течение года. По данным того же опроса, 13,2% этих разработчиков считают, что главной проблемой таких разработок является нехватка программных средств для создания, тестирования и отладки параллельных приложений. Следовательно, в решении задачи автоматического поиска ошибок в исходном коде непосредственно заинтересованы примерно 630.000 программистов.

Целью работы является создание статического анализатора кода, предназначенного для автоматического обнаружения таких ошибок. В исследовании рассматривался язык C++, поскольку к коду именно на этом языке чаще всего предъявляются требования высокой производительности. Так как поддержка технологии OpenMP встроена в Microsoft Visual Studio 2005 и 2008, и некоторые специалисты считают, что именно технология OpenMP вскоре приобретет наибольшую популярность [3], рассматривалась именно эта технология (помимо C++ применяемая также для языков C и Fortran).

Анализ обзоров отладчиков для параллельных программ показывает, что ситуация в этой сфере до сих пор далека от идеала. Применительно к отладке программ, написанных на С++ и использующих OpenMP, как правило, упоминаются TotalView и Intel Thread Checker. Однако, оба эти инструмента предназначены для динамического использования. До недавнего времени направление статического анализа OpenMP программ было практически не освоено. В качестве примера можно привести, пожалуй, только достаточно качественную диагностику, выполняемую компилятором Sun Studio. Статический анализатор VivaMP заполнил это нишу.

2. Применение статического анализа для отладки параллельных программ

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

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

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

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


Статический анализ позволяет просмотреть весь исходный код приложения, не требует от программиста никаких дополнительных усилий и приводит к обнаружению опасных фрагментов кода. Недостаток статического анализа заключается в том, что он не позволяет проверить поведение, зависящее от пользователя. Еще одной проблемой являются ложные срабатывания, уменьшение количества которых требует дополнительных усилий при разработке анализатора. Подробнее вопрос применения статического анализа при разработке параллельных программ рассматривается в статье [4].

В анализаторе VivaMP используется анализ с обходом дерева кода (tree walk analysis). Помимо этого существуют и другие виды статического анализа, предполагающие моделирование выполнения программы, расчет возможных значений переменных и путей выполнения кода. Статический анализ как средство диагностики ошибок в параллельных программах был выбран потому, что данный подход позволяет находить многие ошибки, не диагностируемые динамическими анализаторами. Теперь рассмотрим сами ошибки подробнее.

3. Диагностируемые ошибки

Список возможных ошибок, не обнаруживаемых компилятором Visual Studio, был составлен в результате исследования работ, посвященных параллельному программированию с использованием OpenMP, а также на основе личного опыта авторов. Все ошибки можно разделить на четыре основные категории:

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

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

Приведем примеры ошибок каждого вида и их краткое описание.

3.1. Отсутствие ключевого слова parallel

Рассмотрим простейшую ошибку, которая может возникнуть при неправильном написании директив OpenMP. Поскольку эти директивы имеют достаточно сложный формат, такую ошибку по тем или иным причинам может допустить любой программист. Пример корректного и некорректного кода приведен на Рис. 1.

Рис. 1 . Пример ошибки, вызванной отсутствием ключевого слова parallel

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

3.2. Неправильное применение блокировок

Если программист использует для синхронизации и/или защиты объекта от одновременной записи функции вида omp_set_lock, каждый поток должен содержать вызовы соответствующих функций omp_unset_lock, причем с теми же переменными. Попытка освобождения блокировки, захваченной другим потоком, или отсутствие вызова разблокирующей функции может привести к ошибкам во время выполнения программы и бесконечному ожиданию. Рассмотрим пример кода (см. Рис. 2):

Рис. 2 . Пример некорректного использования блокировок

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

Теперь рассмотрим другую ошибку более подробно и приведем соответствующее правило для анализатора.

3.3. Незащищенный доступ к общей памяти

Эта ошибка может встретиться в любой параллельной программе, написанной на любом языке. Также она называется состоянием гонок (race condition) и суть ее заключается в том, что значение общей переменной, изменяемой одновременно из нескольких потоков, в результате может оказаться непредсказуемым. Рассмотрим простой пример для С++ и OpenMP (см. Рис. 3):

Рис. 3 . Пример состояния гонок

Эту ошибку также можно обнаружить средствами статического анализатора. Рассмотрим правило, по которому статический анализатор VivaMP сможет обнаружить эту ошибку:

Опасными следует считать инициализацию или модификацию объекта (переменной) в параллельном блоке, если объект относительно этого блока является глобальным (общим для потоков).

К глобальным объектам относительно параллельного блока относятся:

  • Статические переменные.
  • Статические члены класса (В версии VivaMP 1.0 не реализовано).
  • Переменные, объявленные вне параллельного блока.

Объект может быть как переменной простого типа, так и экземпляром класса. К операциям изменения объекта относится:


  • Передача объекта в функцию по не константной ссылке.
  • Передача объекта в функцию по не константному указателю (В версии VivaMP 1.0 не реализовано).
  • Изменение объекта в ходе арифметических операций или операции присваивания.
  • Вызов у объекта не константного метода.

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

  • Код не находится в параллельном блоке (нет директивы «parallel»).
  • Модификация объекта защищена директивой «atomic».
  • Код находится в критической секции, заданной директивой «critical».
  • Код находится в критической секции, образованной функциями вида omp_set_lock.
  • Код находится в блоке директивы «master».
  • Код находится в блоке директивы «single».
  • К объекту (переменной) применена директива «threadprivate», либо выражение «private», «firstprivate», «lastprivate» или «reduction». Это исключение не касается статических (static) переменных и статических полей классов, которые всегда являются общими.
  • Инициализация или модификация объекта осуществляется внутри оператора for (внутри самого оператора, а не внутри тела цикла). Такие объекты согласно спецификации OpenMP автоматически считаются локальными (private).
  • Модификация объекта осуществляется внутри секции, заданной директивой section.

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

В заключение этого раздела отметим, что более полный список обнаруженных в результате исследований ошибок и их более подробные описания можно найти в статье [5]. Помимо этого пример программы, демонстрирующей ошибочные и исправленные версии проблемного кода можно найти на сайте проекта VivaMP.

Теперь перейдем к описанию самого анализатора.

4. Анализатор VivaMP

Анализатор VivaMP разработан на основе библиотеки анализа кода VivaCore и вместе с анализатором Viva64 составляет единую линейку продуктов в области тестирования ресурсоемких приложений. Viva64 предназначается для поиска ошибок, связанных с переносом 32-битного ПО на 64-битные платформы. VivaMP предназначен для проверки параллельных приложений, построенных на базе технологии OpenMP. Как и Viva64, VivaMP интегрируется в среду разработки Visual Studio 2005/2008, добавляя новые команды в интерфейс. Настройка анализатора делается через стандартный для среды механизм, диагностические сообщения выводятся так же, как сообщения стандартного компилятора — в окна Error List и Output Window. Помимо этого подробное описание ошибок приведено в справочной системе анализатора, интегрирующейся в справку Visual Studio. Контекстная справка реализована через стандартный механизм среды. Интерфейс анализатора VivaMP, интегрированного в среду Visual Studio приведен на Рис. 4.

Рис. 4 . Интерфейс VivaMP

На данный момент выпущена первая версия анализатора, информацию о которой можно получить по адресу http://www.viva64.com/ru/vivamp-tool/. Первая версия VivaMP диагностирует 19 ошибок, однако, количество собранного материала и результаты экспериментов позволяют существенно увеличить это число (как минимум в два раза) в последующих версиях. Ниже перечислены краткие описания диагностируемых ошибок:

  • Отсутствие ключевого слова «parallel».
  • Отсутствие ключевого слова «omp».
  • Отсутствие ключевого слова «for» (каждый поток выполнит цикл полностью, работа не будет разделена между потоками).
  • Вложенное распараллеливание цикла «for».
  • Отсутствие директивы «ordered» в упорядоченном цикле.
  • Переопределение числа потоков в параллельном коде.
  • Несимметричное использование блокирующих/разблокирующих функций.
  • Зависимость поведения кода от количества выполняющих его потоков (использование функции «omp_get_num_threads» в арифметической операции).
  • Переопределение возможности вложенного распараллеливания в параллельном коде.
  • Одновременное использование общего ресурса (незащищенный вызов функции).
  • Использование директивы «flush» для указателей.
  • Использование директивы «threadprivate». Директива опасна, так как влияет на весь файл. Рекомендуется использовать локальные переменные или явно указывать тип доступа в каждом параллельном блоке.
  • Незащищенное объявление статической переменной в параллельном коде.
  • Незащищенная одновременная операция с переменной.
  • Одновременное изменение переменной посредством вызова функции.
  • Одновременное изменение объекта посредством вызова функции.
  • Переменная ссылочного типа не должна быть объявлена как локальная.
  • Указатель не может быть локальной переменной.
  • Переменная, объявленная как «lastprivate», не изменена в лексически последней параллельной секции.

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

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

Литература

  • Timothy Prickett Morgan. Evans Data Cases. Programming Language Popularity: [http://www.itjungle.com/tug/tug121406-story03.html], 14.12.2006.
  • Michael Suess. Why OpenMP is the way to go for parallel programming: [http://www.thinkingparallel.com/2006/08/12/why-openmp-is-the-way-to-go-for-parallel-programming/], 12.08.2006.
  • Е.А. Рыжков, О.С. Середин. Применение технологии статического анализа кода при разработке параллельных программ. Известия ТулГУ. Технические науки. Вып.3. — Тула: Изд-во ТулГУ, 2008. — 267 с. Стр. 191 — 196.
  • Алексей Колосов, Евгений Рыжков, Андрей Карпов. 32 подводных камня OpenMP при программировании на C++. RSDN Magazine #2-2008. Cтр. 3 — 17.
Найдите ошибки в своем C, C++, C# и Java коде

Предлагаем попробовать проверить код вашего проекта с помощью анализатора кода PVS-Studio. Одна найденная в нём ошибка скажет вам о пользе методологии статического анализа кода больше, чем десяток статей.

Программирование в C++. Не могу найти ошибку в коде.

Вот код:
#include
#include «rus8.h»
#include
using namespace std;

int main()
<
rus();
double a, b, c;//a, b, c — коэффиценты уравнения
double x0, x1, x2, x3, x4, x5;// х1, х2 — корни уравнения
double D;//D-дискриминант
FILE *f_in;
FILE *f_out;
int retcode;
f_in = fopen(«Input.txt», «r»);
if (f_in == NULL)
<
printf(«Ошибка открытия файла Input.txt. \n»);
return 1;
>
retcode = fscanf (f_in, » a=%lg b=%lg c=%lg», &a, &b, &c);
if (retcode !=3)
<
printf («Ошибка чтения данных из файла Input.txt. \n»
«Проверьте корректность данных. \n»);
return 2;
>
retcode = fclose(f_in);
if (retcode == EOF)
<
printf («Ошибка закрытия файла Input.txt. \n»);
return 3;
>
printf(«Вы получии уравнение: %lgx^2%+lgx%+lg=0\n», a, b, c);
f_out = fopen(«Output.txt», «w»);
if (f_out == NULL)
<
printf(«Ошибка открытия файла Output.txt. \n»);
return 4;
>
if ( a==0 )
<

if (b==0)
<
printf («Ошибка!! !Неверное математическое выражение: %lg=0\n», c);
>
x0=(-c)/b;//нахождение корня при а=0
retcode = fprintf (f_out, «%lg — единственный корень\n», x0);
if (retcode !=2)
<
printf («Ошибка записи данных в файл Output.txt. \n»);
return 5;
return 0;
>
return 0;

>
if (a!=0)
<
D = (b)*(b)-4*a*c;//формула нахождения дискриминанта
if (D 0)
<
x4=((-b)+sqrt(D))/(2*a);//формулы нахождения корней
x5=((-b)-sqrt(D))/(2*a);//квадратного уравнения
retcode = fprintf (f_out, «Первый корень%lg\nВторой корень %lg», x4, x5);
if (retcode !=2)
<
printf («Ошибка записи данных в файл Output.txt. \n»);
return 8;
return 0;
>
>
printf(«Уравнение решено. Ответ находится в файле Output.txt\n»);
>
Вот что он выводит:
1>d:\projects\pract2\pract2\main.cpp(15) : warning C4996: ‘fopen’: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1> d:\mvs08\vc\include\stdio.h(237) : see declaration of ‘fopen’
1>d:\projects\pract2\pract2\main.cpp(21) : warning C4996: ‘fscanf’: This function or variable may be unsafe. Consider using fscanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1> d:\mvs08\vc\include\stdio.h(256) : see declaration of ‘fscanf’
1>d:\projects\pract2\pract2\main.cpp(35) : warning C4996: ‘fopen’: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1> d:\mvs08\vc\include\stdio.h(237) : see declaration of ‘fopen’
1>d:\projects\pract2\pract2\main.cpp(66) : warning C4553: ‘==’ : operator has no effect; d >1>d:\projects\pract2\pract2\main.cpp(100) : fatal error C1075: end of file found before the left brace ‘<' at 'd:\projects\pract2\pract2\main.cpp(7)' was matched
1>Build log was saved at «file://d:\projects\pract2\pract2\Debug\BuildLog.htm»
1>pract2 — 1 error(s), 4 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Еще поставил двойное равно == вместо =
x2==-b-sqrt(-D)*i;

А тут пахнет быдлокодом.
return 8;
return 0;

Цукерберг рекомендует:  Javascript - Вопрос по JS.
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих
26.09.2008, 20:53 #1