﻿# Программные ошибки, которых не бывает

Недавно к нам обратился пользователь нашего анализатора PVS\-Studio, который пожаловался на работу инструмента при проверке одного из проектов\.

Наш инструмент выдавал сообщение:

```cpp
Error 155 Cannot open configuration file c:\foo\testfile.c.PVS
  Studio.cfg
```

Здесь надо пояснить, что для каждого проверяемого файла PVS\-Studio создает среди прочих специальный конфигурационный файл \.PVS\-Studio\.cfg, в котором задаются выбранные настройки для модуля анализа \(который является отдельным exe\-файлом\)\.

В процессе переписки выяснилось, что файл, который инструмент не может проверить, называется не testfile\.c, как следует из логики сообщения, а test^file\.c\. И выглядит такое поведение, как будто анализатор "теряет" символ "^"\. Пытаясь найти ошибку, мы выявили, что плагин PVS\-Studio корректно передает имя файла, а проблема возникает собственно в ядре анализатора \(тот самый отдельный exe\-файл\)\.

Сначала мы вроде бы даже нашли, что проблема с этим символом находится "рядом" с библиотекой разбора конфигурационных файлов\. Но при отладке выяснилось странное\. Если в среде Visual Studio \(в которой мы разрабатываем инструмент\) задать параметры командной строки для анализатора как "\-cfg\=c:\\foo\\test^file\.c\.PVS\-Studio\.cfg" и нажать Ctrl\-F5 \(запуск программы\), то получим сообщение:

```cpp
Cannot open configuration file c:\foo\testfile.c.PVS-Studio.cfg
```

То есть ошибка повторяется\.

А вот если нажать просто F5 \(старт отладчика\), то программа\.\.\. корректно работает\! Читатель сразу же скажет: "Ну что же вы, разрабатываете инструмент для программиста, а сами не знаете, что Debug\-версия программы может работать, а Release\-версия \- нет?" Обращаем внимание, что и в первом, и во втором случае запускалась Debug\-версия, просто в разных режимах\.

После экспериментов стало понятно, что ничего не понятно\.

Мы отложили код нашего проекта в сторону и провели простой эксперимент, который может повторить каждый\.

* 1\. Открываем Visual Studio 2005 или 2008 \(без разницы\), создаем Visual C\+\+ Win32 Console Application\.
* 2\. Вставляем всего лишь строку с fprintf так, что в результате получится следующий код:

```cpp
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
  fprintf(stdout, "%s\n", argv[1]);
  return 0;
}
```

* 3\. В настройках режима отладки \(Debugging\-\>Command Arguments\) указываем "test^file\.c" без кавычек\.
* 4\. Запускаем программу \(Debug\-версия\) по Ctrl\-F5\. Получаем:

```cpp
testfile.c
```

то есть символ "^" пропал\.

* 5\. Ставим точку останова \(breakpoint\) на строку "return 0;", нажимаем F5\. Получаем:

```cpp
test^file.c
```

то есть символ "^" есть\.

Как ни странно, но программа ведет себя по\-разному в зависимости от режима запуска\. Вероятно символ "^" обрабатывается как Escape\-последовательность\. Но почему запуск по F5 и Ctrl\-F5 дает разные результаты?

В PVS\-Studio в качестве решения мы выбрали обходной путь\. В случае если в имени конфигурационного файла встречается символ "^", то мы заменим его на другой символ\.