Ошибка анализатора что это

I’ve finished simple asp.net web application project, compiled it, and try to test on local IIS. I’ve create virtual directory, map it with physical directory, then put all necessary files there, including bin folder with all .dll’s
In the project settings, build section, output path is bin
So when i try to browse my app i got:

Server Error in '/' Application.
--------------------------------------------------------------------------------

Parser Error 
Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately. 

Parser Error Message: Could not load type 'AmeriaTestTask.Default'.

Source Error: 


Line 1:  <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="AmeriaTestTask.Default" %>
Line 2:  
Line 3:  <%@ Register assembly="AjaxControlToolkit" namespace="AjaxControlToolkit" tagprefix="ajaxToolkit" %>


Source File: /virtual/default.aspx    Line: 1 

enter image description here

Have read similar problem posts and solution was to set output path to bin, but it is defalut for my project.

asked Feb 10, 2013 at 17:36

igorGIS's user avatar

9

I know i am too late to answer but it could help others and save time.

Following might be other solutions.

Solution 1: See Creating a Virtual Directory for Your Application for detailed instructions on creating a virtual directory for your application.

Solution 2: Your application’s Bin folder is missing or the application’s DLL file is missing. See Copying Your Application Files to a Production Server for detailed instructions.

Solution 3: You may have deployed to the web root folder, but have not changed some of the settings in the Web.config file. See Deploying to web root for detailed instructions.

In my case Solution 2 works, while deploying to server some DLL's from bin directory has not been uploaded to server successfully. I have re-upload all DLL’s again and it works!!

Here is the reference link to solve asp.net parser error.

answered Jan 23, 2014 at 8:46

immayankmodi's user avatar

immayankmodiimmayankmodi

8,0909 gold badges36 silver badges55 bronze badges

0

I had the same issue. Ran 5 or 6 hours of researches. A simple solution seems to be working. I just had to convert my folder to application from iis. It worked fine. (this was a scenario where I had done a migration from server 2003 to server 2008 R2)

(1) Open IIS and select the website and the appropriate folder that needs to be converted. Right-click and select Convert to Application.

enter image description here

answered Sep 13, 2014 at 6:20

Aravinda's user avatar

AravindaAravinda

4951 gold badge7 silver badges17 bronze badges

3

Try changing CodeBehind="Default.aspx.cs" to CodeFile="Default.aspx.cs"

answered Jun 16, 2016 at 6:39

Codeone's user avatar

CodeoneCodeone

1,1632 gold badges15 silver badges40 bronze badges

Sometimes it happens if you either:

  1. Clean solution/build or,
  2. Rebuild solution/build.

If it ‘suddenly’ happens after such, and your code has build-time errors then try fixing those errors first.

What happens is that as your solution is built, DLL files are created and stored in the projects bin folder. If there is an error in your code during build-time, the DLL files aren’t created properly which brings up an error.

A ‘quick fix’ would be to fix all your errors or comment them out (if they wont affect other web pages.) then rebuild project/solution

If this doesn’t work then try changing:
CodeBehind=»blahblahblah.aspx.cs»

to:
CodeFile=»blahblahblah.aspx.cs»

Note: Change «blahblahblah» to the pages real name.

answered Sep 14, 2017 at 15:00

Onga Leo-Yoda Vellem's user avatar

I have solved it this way.

Go to your project file let’s say project/name/bin and delete everything within the bin folder. (this will then give you another error which you can solve this way)

then in your visual studio right click project’s References folder, to open NuGet Package Manager.

Go to browse and install «DotNetCompilerPlatform».

answered Sep 19, 2018 at 9:15

Mo D Genesis's user avatar

Mo D GenesisMo D Genesis

4,8451 gold badge21 silver badges30 bronze badges

Faced the same error when I had a programming error in one of the ASHX files: it was created by copying another file, and inherited its class name in the code behind statement. There was no error when all ASPX and ASHX files ran in IIS Express locally, but once deployed to the server they stopped working (all of them).

Once I found that one ASHX page and fixed the class name to reflect its own class name, all ASPX and ASHX files started working fine in IIS.

answered Oct 5, 2016 at 16:17

ajeh's user avatar

ajehajeh

2,6422 gold badges32 silver badges64 bronze badges

Very old question here, but I ran into the same error and none of the provided answers solved the issue.

My issue occurred because I manually changed the namespace and assembly names of the project after initial creation. Took me a little bit to notice that the namespace in the Inherits attribute didn’t match the updated namespace.

Updating that namespace in the Global.asax markup to match the apps namespace fixed the error for me.

answered Oct 16, 2019 at 20:05

A-A-ron's user avatar

A-A-ronA-A-ron

5291 gold badge5 silver badges14 bronze badges

IIS 7 or IIS 8 or 8.5 version — if you are migrating from 2003 to 2012/2008 make sure web service are in application type instead virtual directory

answered Jul 31, 2015 at 9:53

Chandrashekar Gowda's user avatar

0

In my case, There were new code branch and old code branch was deployed locally in IIS. So it was pointing to old branch code that was not available. So i had deployed my code to IIS with new branch and it is working now.

answered Dec 27, 2017 at 14:02

Jeetendra's user avatar

0

In my case I missed the compile tag in the .csproj file

<Compile Include="Global.asax.cs">
  <DependentUpon>Global.asax</DependentUpon>
  <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Compile>

answered Apr 30, 2018 at 10:24

David's user avatar

DavidDavid

69311 silver badges24 bronze badges

Interesting all the different scenarios..

In my case…I had uploaded my site to GoDaddy and was getting the Parser Error.

I resolved it by commenting out compilers under system.codedom in web.config.
And also add a custom profile for publishing that would precompile during publishing.

  <system.codedom>
    <!--GoDaddy does not compile!-->
    <!--<compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=&quot;Web&quot; /optionInfer+" />
    </compilers>-->
  </system.codedom>

answered Apr 4, 2019 at 23:54

Chris Catignani's user avatar

Chris CatignaniChris Catignani

4,92714 gold badges42 silver badges48 bronze badges

When you add subfolders and files in subfolders the DLL files in Bin folder also may have changed. When I uploaded the updated DLL file in Bin folder it solved the issue. Thanks to Mayank Modi who suggested that or hinted that.

answered Jul 31, 2019 at 5:32

Sam Patirage's user avatar

Looking at the error message, part of the code of your Default.aspx is :

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="AmeriaTestTask.Default" %>

but AmeriaTestTask.Default does not exists, so you have to change it, most probably to the class defined in Default.aspx.cs. For example for web api aplications, the class defined in Global.asax.cs is : public class WebApiApplication : System.Web.HttpApplication and in the asax page you have :

<%@ Application Codebehind="Global.asax.cs" Inherits="MyProject.WebApiApplication" Language="C#" %>

answered Mar 22, 2020 at 15:08

Mario's user avatar

MarioMario

3132 silver badges11 bronze badges

I am too late but let me explain how I solved this problem.

This problem is basically because of improper folders/solution structure.

this issue may occur because
1. If you have copied project from other location and trying to run the project.

so to resolve this go to original location and crosscheck the folders and files again.

this works for me.

answered Sep 21, 2015 at 6:14

Shriganesh Kolhe's user avatar

After a lot of searching ,i found the problem was in my project dll file .i cleaned and rebuild my project when there were compilation errors …
simple solution is to remove all compilation errors in all pages either by removing contents or commenting lines ,then clean and rebuild your project …
this will sort out your problem ..

answered May 19, 2020 at 18:20

abhishek bhardwaj's user avatar

This happens when the files inside the Debug and Release folder are not created properly(Either they are having wrong reference or having overwritten many times). I have faced the same problem in which, i everything works fine when we build the solution, but when i publish the website it gives me same error.
I have solved this in following manner:

  1. Go to your Solution Explorer in Visual Studio and click on show hidden files (if they are not showing ! )
  2. you will find a folder named obj, open it .
  3. Here there are again 2 folder named respectively as Debug and Release.
    Now, delete the content from these two folder, Make sure that you do not delete the folders Debug and Release. Only delete the files and folders inside Debug and Release folder.
  4. Now build and publish your solution and everything will work like charm.

answered Sep 20, 2015 at 11:08

Roshan Parmar's user avatar

Roshan ParmarRoshan Parmar

3,6921 gold badge11 silver badges7 bronze badges

1

Внутренняя ошибка компоненты анализатора. Что это?

Я
   beholder

18.04.07 — 12:22

С помошью v7plus.dll обработка пытается записать XML-файл. Но при методе Записать() вылетает с такой ошибкой никто не  сталкивался?

   ТелепатБот

1 — 18.04.07 — 12:22

   Лефмихалыч

2 — 18.04.07 — 12:23

версии v7plus и msxml какие?

   beholder

3 — 18.04.07 — 12:26

v7plus  — 7.70.0.10
а msxml где посмотреть?

   Лефмихалыч

4 — 18.04.07 — 12:31

%SYSTEMROOT%system32

   beholder

5 — 18.04.07 — 12:38

8.0.7002.0

   beholder

6 — 18.04.07 — 12:42

может что-то с правами на директорию куда он пытается писать файл?

   beholder

7 — 18.04.07 — 12:50

Подниму ветку

   Тяпкин

8 — 18.04.07 — 12:51

Может, и не в тему, но был у меня глюк с командой Сбросить(). Там имя файла указывается строкой, и если в строке была ещё не существующая папка, то вылетал с ошибкой — Неправильное имя файла.

   beholder

9 — 18.04.07 — 13:28

Подниму ветку

   Лефмихалыч

10 — 18.04.07 — 13:34

папки-то все существуют, в которые пишешь?

   beholder

11 — 18.04.07 — 13:35

(10) ну да, КаталогИБ()

   beholder

12 — 18.04.07 — 14:03

Маленький объем, главное, записывает

   Лефмихалыч

13 — 18.04.07 — 14:10

(12) не пишет любые файлы в любые каталоги или только какой-то конкретный файлик в конкретный каталог не пишет?

Чем отличается _маленький_ объем от _большого_?

   beholder

14 — 18.04.07 — 14:15

(13) большой объем примерно 75 мб маленький — 1 мб. Я просто попробовал исскуственно огранизить объем выгружаемой информации

Не пишет конкретный файл в конкретный каталог, пробовал менять каталог — не помогло

   Лефмихалыч

15 — 18.04.07 — 14:22

(14) может в файле дело? или место кончилось на винте? Чудеса ты какие-то расскащываешь…

   beholder

16 — 18.04.07 — 15:16

И под другим пользователем тоже все нормально проходит

   beholder

17 — 18.04.07 — 15:17

права наверное

   beholder

18 — 19.04.07 — 13:47

а я вот подыму ветку, может кто умный пришел

   beholder

19 — 19.04.07 — 15:12

Короче, ОБЪЯВЛЯЕТСЯ МОЗГОВОЙ ШТУРМ!!!

Кидаем сюда самые безумные идеи и способы локализации проблемы.

Не дадим костной материи победить разум!

   beholder

20 — 20.04.07 — 12:27

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

   beholder

21 — 23.04.07 — 16:32

подниму ветку

  

Тяпкин

22 — 23.04.07 — 16:57

(21) Ну, например, такое наблюдение — в типовой Выгрузке Проводок из ЗиК метод Записать() не используется, используют гФайлДанных.Сбросить():

гСчетчикВыгруженныхОбъектов = гСчетчикВыгруженныхОбъектов + 1;

Если гСчетчикВыгруженныхОбъектов % ФормКолвоБуферизуемыхОбъектов = 0 Тогда

   гФайлДанных.Сбросить();

КонецЕсли; где ФормКолвоБуферизуемыхОбъектов = 50;

Может и правда, есть проблемы с размером файла и ЗиК так их обходит, я не знаю.

В СП написано: Сбросить(<?>)

Синтаксис:

Сбросить()

Назначение:

Записывает содержимое в выходной файл и очищает память

Исправление неисправностей во время работы

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

Если результаты по-прежнему вызывают сомнения, проверьте картриджи данной партии с использованием контрольных материалов i-STAT. Если результаты соответствуют значениям контрольных материалов, можно предположить наличие посторонней примеси  в образце, либо ошибки в работе (например, в заборе крови). В противном случае возможна проблема с данной партией картриджей, (например, из-за условий хранения).

Анализатор коды сообщений

С момента включения питания и до его выключения Анализатор i-STAT® выполняет многочисленные проверки качества. Сбой любой из проверок качества приводит к тому, что анализатор останавливает цикл тестирования  и выдает сообщение о причине «cause» и способе преодоления проблемы «action» и код сообщения.

Код причины  [The Cause Code]:

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

Коды 1-15 и  95 обычно обозначают условия связанные с окружающей средой или состоянием анализатора. Эти состояния обычно не опасны и исправятся сами собой с использованием другого картриджа или Электронного симулятора, или после изменения воздействующих условий.

Номер кодаCode Number Причина/Способ преодоленияCause/Action Message on Display Объяснение
1 Dead Batteries /Replace Batteries

Негодная батарея/Замените батарею

Энергии батареи недостаточно, чтобы завершить тестовый цикл. Замените одноразовую литиевую батарею или зарядите аккумулятор.Если вы часто получаете это код  и используете одноразовые батареи, то, возможно, вам следует подумать об использовании аккумуляторов предназначенных для анализатора i-STAT 1.
2 Temperature Out of Range / Check Status Page

Температура вне рабочего диапазона/Проверьте страницу статуса

Анализатор зафиксировал температуру вне рабочего диапазона. Поместите анализатор перед началом выполнения теста в среду с нормальной рабочей температурой и дайте температуре анализатора сравняться с окружающей. Проверьте температуру анализатора по показаниям на странице статуса анализатора.
3 New Software Installed/ Use Electronic Simulator

Установлено новое программное обеспечение/Используйте электронный симулятор

Это сообщение появляется на портативном клиническом анализаторе после установке нового программного обеспечения или, в некоторых случаях, после получения нового настроечного профиля.
4, 8 Analyzer Interrupted /Use Another Cartridge

Работа анализатора прервана / Воспользуйтесь другим картриджем

Анализатор определил, что последний тестовый цикл не был завершен. Это могло случиться, если была вынута батарея или был плохой контакт, когда картридж находился в анализаторе. Слишком короткие батареи не имеют хорошего контакта. Проверьте, что батареи правильно вставлены и хорошо помещаются в анализаторе; проверьте вольтаж батареи на странице статуса анализатора и замените батареи, в случае низкого вольтажа.ЗАМЕЧАНИЕ: Результаты пациента, показанные перед появлением  этого кода, являются достоверными.
5, 6, 9 Analyzer Interrupted /Ready for Use Работа анализатора прервана /Готов к работе Портативный клинический анализатор не смог обновить изображение на дисплее. Это может произойти, если питание прервется, прежде чем анализатор сам отключит питание. Проверьте, что батареи правильно вставлены и хорошо помещаются в анализатор. Слишком короткие батареи не имеют хорошего контакта. Проверьте вольтаж батареи на странице статуса анализатора.
7 Batteries Changed /Ready for Use Батарея заменена /Готов к работе Это нормальная реакция Анализатора, на замену батареи после появления кода 1.
10 Temperature In Range /Ready for Use

Температура в рабочем диапазоне /Готов к работе

Температура восстановилась в рабочем диапазоне после появления кода 2.
11 Date Invalid / Check Clock on Status Page

Некорректная дата /Проверьте состояние часов на странице статуса

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

Invalid or Expired CLEW/ See Manual

Некорректное или с истекшим сроком CLEW /Смотрите руководство

Комплект стандартизации CLEW просрочен. Загрузите корректный CLEW.Дата на системных часах превосходит дату истечения срока годности программного обеспечения CLEW. Проверьте дату системных часов.
13

Invalid or Expired CLEW/ See Manual

Некорректное или CLEW с истекшим сроком /Смотрите руководство

CLEW  испорчен или несовместим с программным обеспечением (JAMS), или в анализаторе отсутствует CLEW. Загрузите корректный CLEW. Если этот код появляется после обновления программного обеспечения и в CDS задействована настройка приложения, измените версию CLEW в настройке профиля  на последнюю версию и передайте профиль в анализатор.
14 Analyzer Error / SeeManual

Ошибка анализатора /Смотрите руководство

Настройка профиля повреждена. ретранслируйте настройку профиля. Если снова возникнет код 14, обратитесь в сервисную службу i-STAT или в вашу локальную организацию поддержки за дополнительной помощью.
15

Barcode Does Not Match Cartridge Type

Штрих код не совпадает с типом картриджа

Штрих-код, сканированный пользователем, не совпадает с типом иммуно-теста картриджа, указываемого идентификационной микросхемой картриджа. Пользователь должен использовать другой картридж, и быть аккуратным при сканировании штрих-кода с его упаковки перед установкой его в анализатор.
95 Test Cancelled by OperatorТест прерван оператором Это сообщение появляется в сохраненной записи теста на анализаторе i-STAT 1, если питание анализатора было выключено  до ввода обязательной информации.

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

Номер кодаCode Number Причина/Способ преодоленияCause/Action Message on Display Объяснение
19 No Clot Detected / SeeManual

Сгусток не обнаружен /Смотрите руководство

Во время цикла PT/INR, не был обнаружен сгусток. Воспользуйтесь другим картриджем. Если код 19 возникает снова и снова, протестируйте образец  другим способом.
22, 25

Cartridge Error / UseAnother Cartridge

Ошибка картриджа /используйте другой картридж

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

Cartridge Error / UseAnother Cartridge

Ошибка картриджа /используйте другой картридж

Электрическое сопротивление калибровочной жидкости (R cal), используемой для проверки концентрации электролита, не соответствует спецификации. Это возникает в том случае, если упаковка калибратора была нарушена перед тестом, что привело к испарению и повышению концентрации электролита.Кроме концентрации электролита, R cal так же подвержена влиянию температуры,  высоте и ширине сегмента жидкости над кондуктометрическим сенсором. Анализатор учитывает температуру, но высота и ширина сегмента жидкости может меняться от одной партии картриджей к другой. Анализатор запрограммирован таким образом, чтобы компенсировать эти различия между партиями и поддерживать усредненные значения R cal, измеренные во время предыдущих тестов. Временами, различие между значениями R cal для двух партий картриджей оказывается достаточно большим, что и вызывает появление кода 24 при нескольких первых прогонах картриджей новой партии. Код ошибки  24 должен исчезнуть, по мере того как в процессе работы изменяется усредненное значение. Однако, если код  24 продолжает возникать после более чем 3 прогонов картриджей, обратитесь в сервисную службу i-STAT или в вашу локальную организацию поддержки.
26

Cartridge Error / UseAnother Cartridge

Ошибка картриджа /используйте другой картридж

Этот код появляется вследствие сбоев в специфических коагуляционных  проверках качества: преждевременной активации субстрата, ненормально низких уровней субстратов или некорректных движений потоков.
20, 27-29, 32, 33, 40, 41, 45, 87 Cartridge Error / UseAnother Cartridge

Ошибка картриджа /используйте другой картридж

Эти коды обозначают такие проблемы в картриджах как: слишком раннее или слишком позднее поступление жидкости калибратора или не появление его вообще, шум в сигналах потока калибратора. Коды 20, 27, 41, и 87 могут быть вызваны плохим контактом и могут быть исправлены прочисткой контактных иголок [pins] в анализаторе с использованием керамического очищающего картриджа. Особенности процедуры прочистки описаны в конце этого бюллетеня.Коды 20, 27, и 33 могут наблюдаться после хранения картриджей при комнатной температуре более 7 дней.Код проверки качества 45 появляется, когда картридж запускается в работу без выравнивания его температуры до комнатной. Чтобы уменьшить количество кодов проверки качества следите за условиями хранения картриджей, и давайте им достаточно времени, чтобы согреться до комнатной температуры после хранения их в холодильнике.
42, 43

Cartridge Error / UseAnother Cartridge

Ошибка картриджа /используйте другой картридж

Эти коды указывают, что кондуктометрический сенсор (код 42) или амперометрический сенсор (код 43) не соответствуют параметрам спецификации. Это может быть вызвано предшествующим нарушением упаковки калибратора, загрязнением контактной колодки картриджа или загрязнением соединительного узла самого анализатора.
79-81 Cartridge Error / UseAnother CartridgeОшибка картриджа /используйте другой картридж К появлению этого кода приводит плохой контакт между температурным датчиком анализатора и металлизированной стенкой микросхемы картриджа. Причинами могут быть некачественная металлизация на микросхеме, загрязнение металлизированной поверхности, погнутый или сломанный температурный датчик в анализаторе.
21 Cartridge Preburst / Use Another Cartridge

Картридж поврежден /используйте другой картридж

Этот код указывает на то, что анализатор зафиксировал жидкость на сенсоре до того, как она должна была там оказаться. Возможные причины: неправильное обращение с картриджем (сдавливание в средней части картриджа), плохие условия хранения картриджа (замораживание), или повторный запуск уже использованного картриджа.
31, 34, 44

Unable to Position Sample / Use Another Cartridge

Невозможность перемещения образца /используйте другой картридж

Анализатор не обнаружил движения образца через сенсор. Это может произойти вследствие образования сгустка в образце (особенно у новорожденных), не закрытия крышки с фиксатором картриджа или дефектного картриджа.Коды 31 и 34 могут наблюдаться при хранении картриджей при комнатной температуре более 7 дней.
35, 36 Sample Positioned Short of Fill Mark / UseAnother Cartridge

Образец перемещен до метки заполнения /используйте другой картридж

Картридж был заполнен слабо. Образец должен достигать метки заполнения. Возьмите другой картридж.Коды 35 и 36 могут появляться при хранении картриджей при комнатной температуре более 7 дней.
30, 37

Sample Positioned Beyond Fill Mark / UseAnother Cartridge

Уровень образца выходит за нижний предел  метки заполнения/ используйте другой картридж

Картридж переполнен. Образец вышел за метку заполнения. Возьмите другой картридж.Код 30 может появляться при хранении картриджей при комнатной температуре более 7 дней.
38, 39 Insufficient Sample /Use Another Cartridge 

Неподходящий образец /используйте другой картридж

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

Cartridge Error / UseAnother Cartridge 

Ошибка картриджа /используйте другой картридж

Анализатор не зафиксировал перемещения образца через сенсор. Это могло произойти вследствие образования сгустка в образце (особенно у новорожденных), не закрытия крышки с фиксатором картриджа, или дефектом самого картриджа.
47 Cartridge Not Inserted Properly / Reinsert Cartridge 

Картридж некорректно вставлен /используйте другой картридж

Этот код говорит о том, что картридж или электронный симулятор не вставлен до конца. Заново вставьте картридж или электронный симулятор. Если проблема сохраняется и/или пользователь уверен, что картридж или симулятор вставлены правильно, этот код может указывать на проблему анализатора. Обратитесь в сервисную службу  i‑STAT или в вашу локальную службу поддержки  за дополнительной помощью.
48

Analyzer Error / SeeManual

Ошибка анализатора /Смотрите руководство

Этот код указывает, что картридж или Электронный симулятор был перекошен при установке. Вставляйте картридж или симулятор в порт картриджей прямо. Если проблема повторяется, и пользователь уверен, что вставил картридж или симулятор корректно, этот код может указать на проблему в анализаторе. Обратитесь в сервисную службу  i‑STAT или в вашу локальную службу поддержки  за дополнительной помощью.
49 Poor Contact Detected/ See Manual 

Плохой контакт /Смотрите руководство

Система обнаружила проблему с одной из иголок коннектора (соединительного узла анализатора) при чтении идентификационной микросхемы  у  картриджа для иммуно-анализа. Иногда это может быть исправлено прочисткой иголок [pins] коннектора анализатора с помощью керамического очищающего картриджа. Особенности процедуры прочистки описаны в конце этого бюллетеня.Замечание: Если у вас нет керамического очищающего картриджа,  обратитесь в сервисную службу  i‑STAT или в вашу локальную службу поддержки  за дополнительной помощью.

Следующие состояния связаны с электронными или механическими сбоями анализатора.

Номер кодаCode Number Причина/Способ преодоленияCause/Action Message on Display Объяснение
50 Analyzer Error / UseElectronic Simulator 

Ошибка анализатора /Используйте электронный симулятор

Мотор продвинулся слишком далеко. Запуск симулятор может не обнаружить эту проблему. Запустите симулятор и если анализатор отработает нормально, запустите картридж ,чтобы проверить не возникнет ли ошибка и если не возникнет, продолжайте пользоваться анализатором. Если код ошибки будет выдан снова, обратитесь в сервисную службу  i‑STAT или в вашу локальную службу поддержки  за дополнительной помощью.Если на анализаторе i-STAT 1 тестируются иммуно-ассей картриджи, это код может быть вызван плохим электрическим контактом между  анализатором i-STAT 1 и картриджем. Иногда это может быть исправлено прочисткой иголок [pins] коннектора анализатора с помощью керамического очищающего картриджа. Особенности процедуры прочистки описаны в конце этого бюллетеня.Замечание: Если у вас нет керамического очищающего картриджа то  обратитесь в сервисную службу  i‑STAT или в вашу локальную службу поддержки  за дополнительной помощью.Коды 126 и  128 иногда также связаны с электрическими контактами. Если вы сталкиваетесь с многократным появлением этих трех кодов (50, 126, и 128) в течение короткого промежутка времени, рассмотрите вопрос о возвращении анализатора для ремонта и замены.Присутствие пузырьков в образце во время работы картриджа имуно-ассей, в некоторых условиях, также может стать причиной появление этого кода.
51 Analyzer Error / UseElectronic Simulator 

Ошибка анализатора /Используйте электронный симулятор

Мотор продвинулся слишком далеко. Используйте симулятор. Если ошибка возникает во время работы  ACT картриджа, запустите картридж еще раз. Если этот код не появится вновь, продолжайте использовать анализатор. В некоторых условиях низкий заряд батареи может быть причиной появления этого кода вместо кода 1. Обновите батареи. Если код повторится вновь, обратитесь в сервисную службу i-STAT или в вашу местную службу поддержки за помощью.
52

Analyzer Error / UseElectronic Simulator

Ошибка анализатора /Используйте электронный симулятор

Мотор остановился во время работы. Запустите имитатор. Если ошибка возникает во время работы  ACT картриджа, запустите картридж еще раз. Если этот код не появится вновь, продолжайте использовать анализатор. Если код повторится вновь, обратитесь в сервисную службу i-STAT или в вашу местную службу поддержки за помощью.
58-62

Analyzer Error / UseElectronic Simulator

Ошибка анализатора /Используйте электронный симулятор

Анализатор обычно восстанавливает свою работоспособность после этих ошибок. Эти ошибки могут быть обнаружены электронным имитатором. Если анализатор проходит тестирование Электронного имитатора, продолжайте им пользоваться, если нет, проверьте напряжение батарей  и протестируйте анализатор другим симулятором, чтобы исключить проблему в самом симуляторе. Если код продолжает появляться, обратитесь в сервисную службу i-STAT или в вашу местную службу поддержки за помощью.
23, 53, 55-57, 63,

Analyzer Error / SeeManual

Ошибка анализатора /Смотрите Руководство

Это механические или электронные сбои, после которых анализатор может оказаться неспособным восстановиться.
65-68, 70, 72-74, 82, 85, 86, 89-94, 96, 97 Код 23 может быть вызван плохим электрическим контактом между  анализатором i-STAT 1 и микросхемой картриджа. Иногда это может быть исправлено прочисткой иголок [pins] коннектора анализатора с помощью керамического очищающего картриджа. Особенности процедуры прочистки описаны в конце этого бюллетеня.Код  70 может появиться в Портативном клиническом анализатору [Portable Clinical Analyzer] если пользователь нажмет клавишу DIS  до запуска Электронного симулятора после обновления программного обеспечения. Если это случится, переустановите батареи, чтобы перезапустить анализатор и затем запустите электронный симулятор.Коды 82 и 92 обычно указывают на проблему с датчиком давления в анализаторе. Если код сохраняется, обратитесь в сервисную службу    i-STAT или в вашу местную службу поддержки за помощью.Частота появления кода проверки качества 55 может быть увеличена, когда картриджи запускают в работу не дав им достаточно времени, для выравнивания их температуры с окружающей. Чтобы снизить количество кодов проверки качества, проверяйте условия хранения картриджей i-STAT и давайте картриджам, охлажденным в холодильнике достаточно времени, чтобы согреться до комнатной температуры.Код 56 появляется, когда анализатор обнаруживает шум в температурной цепи. Этот шум может быть результатом электронных помех. При появлении этого кода, анализатор следует перенести в другое место подальше от потенциального источника помех. Если код появится и на новом месте, анализатор следует вернуть для обслуживания.Код 86 может появиться тогда, когда анализатор i-STAT Analyzer хранился в устройстве загрузки/подзарядки [iSTAT Downloader/Recharger] без адекватной вентиляции. Эта проблема может быть решена перемещением анализатора в вентилируемое  место, свободное от внешних источников нагрева, таких как вентиляторы с обогревом или другого электронного оборудования. Если код сохраняется, или код 86 появляется у портативного клинического анализатора или анализатора i-STAT 1 без устройства загрузки /подзарядки, обратитесь в сервисную службу i-STAT или в вашу местную службу поддержки за помощью.Для других кодов, дважды запустите электронный симулятор, затем запустите картридж с образцом. Если анализатор проходит тест электронного симулятор и при запуске образца не возникает ошибок контроля качества, продолжайте пользоваться этим анализатором. Если анализатор не проходит проверку симулятор или появляются ошибки контроля качества по время тестирования образца, обратитесь в сервисную службу i-STAT или в вашу местную службу поддержки за помощью.
69 Cartridge Type Not Recognized / UseAnother Cartridge

Тип картриджа не распознан / воспользуйтесь другим картриджем

Этот код может быть следствием использования типа картриджа, несовместимого с версией программного обеспечения анализатора или использования картриджа с истекшим сроком годности. Проверьте срок годности на коробке картриджа или на упаковке картриджа. Если срок годности еще не истек и если начинает использоваться новый тип картриджей, обратитесь в сервисную службу i-STAT или в вашу местную службу поддержки за обновлением программного обеспечения.При работе картриджей коагуляционных тестов, Код 69 может быть вызван плохим электрическим контактом между  анализатором i-STAT 1 и микросхемой картриджа. Иногда это может быть исправлено прочисткой иголок [pins] коннектора анализатора с помощью керамического очищающего картриджа. Особенности процедуры прочистки описаны в конце этого бюллетеня.Во время работы иммуно-ассей картриджей, этот код может быть показан, если была введена неверная информация в ответ на подсказку «Введите или сканируйте номер партии картриджа» [«Enter or Scan Cartridge Lot Number»].Анализатор ожидает, что будет сканирован штрих-код на задней стороне картриджа. Корректный штрих-код выглядит следующим образом:For immunoassay cartridges, the instrument will not accept keypad entries of the cartridge lot number nor a scan of the barcode on the cartridge box.This condition may be due to an aberrant cartridge. However, if the condition occurs repeatedly on one analyzer, the analyzer may need repair. Contact i-STAT Technical Services or your local support organization for further assistance.

Коды в диапазоне от 120 –138 и 140 – 151 указывают на сбой во время цикла иммунного картриджа. В большинстве случаев этот картридж считается уже израсходованным и нужно использовать другие картриджи. Только анализатор i‑STAT 1 выдает эти коды, так как портативный клинический анализатор [Portable Clinical Analyzer] не поддерживает иммунные циклы.

Номер кодаCode Number Причина/Способ преодоленияCause/Action Message on Display Объяснение
120-122, 124, 125, 133, 144, 148 Cartridge Error / UseAnother Cartridge

Ошибка картриджа /Используйте другой картридж

Эти коды указывают на проблему с перемещением анализирующей жидкости во время работы картриджа. Возьмите другой картридж.
123

Cartridge Error / UseAnother Cartridge

Ошибка картриджа /Используйте другой картридж

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

Cartridge Error / UseAnother Cartridge

Ошибка картриджа /Используйте другой картридж

Во время работы картриджа контроль качества не смог проверить целостность анализирующей жидкости. Однако, этот код может быть также связан с плохим электрическим контактом между анализатором i‑STAT 1 и картриджем. Иногда это может быть исправлено прочисткой иголок [pins] коннектора анализатора с помощью керамического очищающего картриджа. Особенности процедуры прочистки описаны в конце этого бюллетеня.Замечание: Если у вас нет очищающего керамического картриджа, обращайтесь в службу сервиса i-STAT 1-800-366-8020, меню 1.Коды 50 и 128 иногда также связаны с электрическими контактами. Если вы сталкиваетесь с многократным появлением этих трех кодов (50, 126, и 128) в течение короткого промежутка времени, рассмотрите вопрос о возвращении анализатора для ремонта и замены.
127

Cartridge Error / UseAnother Cartridge

Ошибка картриджа /Используйте другой картридж

Увлажнение сенсора было зафиксировано до первоначального перемещения образца.  Возможно переполненный или уже использованный картридж. Возьмите другой картридж.
128, 131,132, 134, 135 — 138

Cartridge Error / UseAnother Cartridge

Ошибка картриджа /Используйте другой картридж

Эти коды чаще всего связаны с плохим заполнением картриджа иммуно-ассей, наличием в образце пузырьков, или резким вставлением картриджа в анализатор.Рекомендации по правильному заполнению:1. Сбросьте (всегда) 1 каплю из приспособления для переноса образца, чтобы избавиться от невидимых пузырьков.2. Создайте одну каплю немного больше чем окружность приемной ячейки.3. Коснитесь каплей (только) окружности приемной ячейки позволив картриджу втянуть в себя образец.4. Убедитесь, что объем образца, находится на одной линии с верхней частью КРАСНОЙ ЛИНИИ ЗАПОЛНЕНИЯ на рисунке.5. Закройте скользящую крышку слева направо.Рекомендации по вставлению картриджа:1. После закрытия картриджа, возьмите закрытый картридж большим и указательным пальцами.2. Вставляйте картридж в анализатор осторожно до появления тихого щелчка.
129, 142, 143

Cartridge Error / UseAnother Cartridge

Ошибка картриджа /Используйте другой картридж

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

Cartridge Error / UseAnother Cartridge

Ошибка картриджа /Используйте другой картридж

Анализатор обнаружил наличие пузырька воздуха в сегменте образца. Возьмите другой картридж.
140

Lot Expired

Срок годности партии истек

Анализатор обнаружил картридж с истекшим сроком годности. Проверьте дату срока годности и повторите тест с картриджем из партии с не истекшим сроком годности.
141

Test Canceled by Operator

Тест отменён оператором

Этот код выдается, если штрих-код картриджа не был сканирован в течение 60 секунд после вставления картриджа. The correct barcode to scan is the barcode on the cartridge portion pack, not the one on the cartridge box. An example of the portion pack barcode is found in the table listing for code 69 above.
145 Cartridge Error / UseAnother Cartridge

Ошибка картриджа /Используйте другой картридж

Анализатор не смог зафиксировать поступление жидкости во время начального перемещения образца. Это может быть вызвано a(n):• утечкой в картридже,• непотным закрытием картриджа. Перед вставлением картриджа убедитесь, что скользящая крышка  полностью закрыта• недостаточное заполнение картриджа. Когда капля образца касается приемной ячейки, иммуно-ассей картриджа картридж автоматически заполняется  с постоянной скоростью за счет сил поверхностного натяжения. Попытки впрыскивать образец в ячейку или добавление большего количества образца не ускорят заполнения картриджа. Дождитесь, пока образец достигнет отметки «заполнить до» [«fill to»] и затем закройте картридж.
146 Cartridge Error / UseAnother Cartridge

Ошибка картриджа /Используйте другой картридж

Переполнение картриджа. Повторите тест.
147

Analyzer Error / SeeManual

Ошибка анализатора/Смотрите руководство

Для того, чтобы работать с картриджами иммуно-ассей анализатор i‑STAT 1 должен иметь символ• и быть настроен дляа) штрих-кодов обязательно илиб) Информации о картриджах в первую очередь или номера партии картриджей обязательно.Если два этих условия не выполняются анализатор показывает этот код ошибки.
149 — 151 Cartridge Error / UseAnother Cartridge

Ошибка картриджа /Используйте другой картридж

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

Следующие состояния связаны с электронным симулятором

КодCode ОбъяснениеExplanation Что делать / How to Respond
Буквенный код Смотрите кодированные сообщения анализатора. Смотрите кодированные сообщения анализатора.
L Потенциометрический канал вышел за пределы спецификации. Может возникнуть, если на контактных иголках [pins] внутри анализатора собирается влага, когда анализатор подвержен изменению температуры. Дайте анализатору уравнять температуру с окружающей средой в течение 30 минут и повторите тест. Если код появится снова, верните анализатор.
G Амперометрический канал вышел за пределы спецификации. Может Can иметь место, если внешний имитатор не вставлен ровно. Повторно вставьте имитатор ровно. Если код появится снова, верните анализатор.
R, r Значение сопротивления, полученное  в кондуктометрическом канале, вышли за пределы спецификации. Верните анализатор.
t Сбой датчика температуры. Верните анализатор.
B Потенциометрический канал вышел за пределы спецификации. Верните анализатор.

ЗАМЕЧАНИЕ: Всякий раз, когда появляются повторяющиеся коды ошибок, которые не могут быть решены или исправлены с помощью обучения, обратитесь в службу технического сервиса i‑STAT или в вашу местную организацию поддержки за помощью.

Вы можете круглосуточно воспользоваться нашим

онлайн-помощником (БОТ) в телеграмм (для перехода—нажмите)

по работе с данным оборудованием, там же возможна

связь с технической поддержкой.

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

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

Введение

Всё началось с публикации «Почему я не люблю синтетические тесты». Можно сказать, что эта статья писалась для себя про запас. Иногда в дискуссиях мне требуется пояснить, почему мне не нравятся те или иные синтетические тесты. Каждый раз писать длинные ответы тяжело, поэтому я давно планировал подготовить статью-ответ, на которую смогу давать ссылку. И когда я рассматривал itc-benchmarks, то понял, что это хороший момент написать текст, пока у меня свежи впечатления и можно выбрать пару тестов, которые я могу включить в статью.

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

Текст статьи может относиться к любому инструменту, PVS-Studio собственно тут ни при чем. Аналогичную статью мог бы написать кто-то из разработчиков GCC, Coverity или Cppcheck.

Ручная работа с ложными срабатываниями

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

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

Дам разъяснения, чтобы более не возвращаться к обсуждению этой темы. PVS-Studio предоставляет несколько механизмов для устранения ложных срабатываний, которые в любом случае неизбежны:

  • Подавление предупреждения в конкретной строке с помощью комментариев.
  • Массовое подавление предупреждений, возникающих из-за макроса. Это также осуществляется с помощью специальных комментариев.
  • Аналогично для строк кода, содержащих определённую последовательность символов.
  • Полное отключение неактуальных для данного проекта диагностик с помощью настроек или специальных комментариев.
  • Исключение из анализа части кода с помощью #ifndef PVS_STUDIO.
  • Изменение настроек некоторых диагностик с помощью комментариев специального вида. Про них говорится в описании конкретных диагностик (см. в качестве примера V719: V719_COUNT_NAME).

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

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

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

Теоретическая справка

Теперь немного теории. Каждое диагностическое сообщение анализатора оценивается двумя характеристиками:

  • Критичность ошибки (насколько она фатальна для программы).
  • Достоверность ошибки (какова вероятность, что найден настоящий дефект, а не просто непонятный анализатору код).

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

Рисунок 1. Диагностики можно оценивать по критичности и достоверности.

Рисунок 1. Диагностики можно оценивать по критичности и достоверности.

Приведу пару поясняющих примеров. Диагностика A, определяющая что в *.cpp файле нет заголовка из комментариев, будет располагаться в правом нижнем углу. Забытый комментарий не приведёт к сбою программы, хотя и является ошибкой с точки зрения принятого в команде стандарта кодирования. При этом очень точно можно определить, есть комментарий или нет. Поэтому достоверность ошибки высокая.

Диагностика B, говорящая, что некоторые из членов класса не инициализируется в конструкторе, будет размещаться в середине верней части. Достоверность этой ошибки не очень высокая, так как анализатор мог просто не понять, как и где инициализируется этот член (это сложно). Инициализацию программист может выполнить уже после того как отработает конструктор. Таким образом, неинициализированный член в конструкторе вовсе не обязательно является ошибкой. Зато эта диагностика находится в верхней части графика, так как если это действительно ошибка, то она критическим образом сказывается на работоспособности программы. Использование неинициализированной переменной — это серьезный дефект.

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

Рисунок 2. Упрощенный вариант классификации. Используется 4 ячейки.

Рисунок 2. Упрощенный вариант классификации. Используется 4 ячейки.

Так, например, поступали авторы анализатора Goanna, пока их не купила компания Coverity, которую в свою очередь потом купила компания Synopsys. Они как раз классифицировали предупреждения, выдаваемые анализатором, относя их к одной из 9 ячеек:

Рисунок 3. Фрагмент из Goanna reference guide (Version 3.3). Используется 9 ячеек.

Рисунок 3. Фрагмент из Goanna reference guide (Version 3.3). Используется 9 ячеек.

Впрочем, и этот способ непривычен и неудобен для использования. Программистам хочется, чтобы предупреждения были расположены на одномерном графике: не важно -> важно. Это привычно, тем более, что на том же принципе строятся предупреждения компиляторов, разделенные на разные уровни.

Свести двумерную классификацию к одномерной непросто. Вот как мы поступили в анализаторе PVS-Studio. У нас просто нет нижней части двумерного графика:

Рисунок 4. Мы проецируем предупреждения высокого уровня критичности на линию. Ошибки начинают классифицироваться по достоверности.

Рисунок 4. Мы проецируем предупреждения высокого уровня критичности на линию. Ошибки начинают классифицироваться по достоверности.

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

Таким образом, нам надо классифицировать ошибки по уровню их достоверности. Этот уровень достоверности есть не что иное, как распределение сообщений анализаторов по трем группам (High, Medium, Low).

Рисунок 5. Фрагмент интерфейсного окна PVS-Studio. Включен просмотр диагностик общего назначения уровня High и Medium.

Рисунок 5. Фрагмент интерфейсного окна PVS-Studio. Включен просмотр диагностик общего назначения уровня High и Medium.

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

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

Примечание. Конечно, и тут есть определенная относительность. Например, в PVS-Studio имеется предупреждение, V553 которое анализатор выдаёт, когда встречает функцию длиной более 2000 строк кода. Такая функция не обязательно должна содержать ошибку. Но на практике, крайне высока вероятность, что эта функция служит источником ошибок. Такую функцию невозможно протестировать юнит-тестами. Можно рассматривать наличие такой функции в коде как дефект. Впрочем, подобных диагностик всего несколько и основная задача анализатора — это поиск выходов за границы массива, неопределённого поведения и прочих фатальных ошибок (см. таблицу).

Ложные срабатывания и уровни достоверности

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

Кратко: Уровни — это достоверность выявленной ошибки.

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

Рисунок 6. Оставлять что-то про запас хорошо. Но в какой-то момент надо уметь остановиться.

Рисунок 6. Оставлять что-то про запас хорошо. Но в какой-то момент надо уметь остановиться.

Читателей видимо насторожили мои слова, что могут исчезнуть и полезные сообщения. Не вижу смысла это отрицать. Такая вероятность существует, но она столь несущественна, что волноваться об этом не следует. Я покажу на примерах, что брать в расчет эти случаи смысла нет. Но давайте начнем с темы размещения сообщений на разных уровнях.

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

char *p = (char *)malloc(strlen(src + 1));

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

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

У этой диагностики, кстати, даже нет ни одного исключения. Если нашли такой паттерн, значит ошибка.

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

y = (A)(B)(A)(B)x;

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

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

Мы интерпретируем уровни так:

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

if (A == B)
  A = 1; B = 2;

Возможно, ошибки здесь нет и фигурные скобки не нужны. Есть малюсенькая вероятность, что программист всегда хотел присваивать переменной B значение 2. Однако, думаю все согласятся, что такой код надо переписать, даже если ошибки нет:

if (A == B)
  A = 1;
B = 2;

Medium (второй уровень). Этот код кажется содержит ошибку, но анализатор не уверен. Если Вы исправили все предупреждения уровня High, то будет полезно позаниматься и предупреждениями уровня Medium.

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

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

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

Рассмотрим, как диагностика может перемещаться по разным уровням. Для примера, возьмем диагностику V572, которая предупреждает о подозрительном явном приведении типа. С помощью оператора new создается объект класса, указатель на который затем кастится к другому типу:

T *p = (T *)(new A);

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

Если же создается массив элементов, а затем приводится к указателю на базовый класс, это гораздо опаснее:

Base *p = (Base *)(new Derived[10]);

Здесь анализатор выдаст предупреждение уровня High. Размер базового класса может быть меньше наследника и тогда при доступе к элементу p[1] мы «влезем не пойми куда» и будем работать с некорректными данными. Даже если пока размер базового класса и наследника совпадает, то все равно этот код следует править. Пока программисту может везти, но очень легко всё сломать, добавив в класс-наследник новый член класса.

Есть и обратная ситуация, когда происходит приведение к тому же типу:

T *p = (T *)(new T);

Такой код может появляться, когда кто-то слишком долго работал с C и забыл, что в отличии от вызова функции malloc обязательное приведение типа не нужно. Или в результате рефакторинга старого кода, при котором C программа, превращается в C++ программу.

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

В комментариях к предыдущей статье, люди переживали, что могут случайно исчезнуть предупреждения, которые хоть и с малой вероятностью, но могут указывать на ошибку. Как правило, такие сообщения не исчезают, а перемещаются на Low уровень. Один из таких примеров мы как раз только что рассмотрели: «T *p = (T *)(new T);». Ошибки здесь нет, но вдруг что-то не так… Желающие имеют возможность изучить код.

Давайте рассмотрим другой пример. Диагностика V531: подозрительно умножать один sizeof на другой sizeof:

size_t s = sizeof(float) * sizeof(float);

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

Однако, есть ситуация, когда уровень предупреждение заменяется на Low. Так происходит, когда одним из множителей выступает sizeof(char).

Все выражения «sizeof(T) * sizeof(char)» которые мы наблюдали более чем на ста проектах не являлись ошибками. Почти всегда это были какие-то макросы, где такое умножение получалось в силу подстановки одного макроса в другой.

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

Рисунок 7. Теперь читатель знает, что он всегда может отправиться в плавание по бескрайним просторам предупреждений уровня Low.

Рисунок 7. Теперь читатель знает, что он всегда может отправиться в плавание по бескрайним просторам предупреждений уровня Low.

Исключения в диагностиках

Исключения бывают как действующие на отдельные диагностики, так и на группы диагностик. Начнем с «исключений массового поражения». В программах есть код, который никогда не выполняется. В нём на самом деле можно вообще не искать ошибки. Раз код не выполняется, то ошибки никак не проявят себя. Поэтому многие диагностики не применяются к невыполняемому коду. Поясню это на примере:

int *p = NULL;
if (p)
{
  *p = 1;
}

При разыменовании указателя, его единственное возможное значение NULL. Больше здесь нет никакого другого значения, которое могло бы храниться в переменной ‘p’. Однако, срабатывает исключение, что разыменование находится в коде, который никогда не выполняется. А раз он не выполняется, то и никакой ошибки нет. Разыменование будет выполняться только тогда, когда в переменную p поместят значение, отличное от NULL.

Кто-то может сказать, что предупреждение могло бы быть полезно, так как подскажет, что условие всегда ложно. Но это забота других диагностик, например, V547.

Будет ли кому-то полезно, если анализатор начнёт предупреждать о том, что в приведённом выше коде разыменовывается нулевой указатель? Нет.

Теперь перейдём к частным исключениям в диагностиках. Вернемся к уже рассмотренной нами ранее диагностике V572:

T *p = (T *)(new A);

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

(void) new A();

Объект создают и сознательно оставляют жить до окончания работы программы. Эта конструкция не могла появиться случайно из-за опечатки. Это сознательное действие по подавлению предупреждений компиляторов и анализаторов на запись вида:

new A();

Многие инструменты будут ругаться на такую конструкцию. Компилятор/анализатор подозревает, что человек забыл записать указатель, который вернёт оператор new. Поэтому человек сознательно использовал подавление предупреждений, добавив приведение к типу void.

Да, этот код странен. Но раз человек просит оставить этот код в покое, то так и надо поступить. Задача анализатора искать ошибки, а не заставлять человека писать ещё более изощрённые конструкции, чтобы запутать компилятор/анализатор и избавиться от предупреждений.

Будет ли кому-то полезно все равно выдавать предупреждение? Нет. Тот, кто писал этот код, спасибо не скажет.

Теперь вернемся к диагностике V531:

sizeof(A) * sizeof(B)

Есть ли случаи, когда вообще не стоит выдавать никакие сообщения, даже уровня Low? Да, есть.

Типовая задача: надо вычислить размер буфера, размер которого кратен размеру другого буфера. Скажем есть массив из 125 элементов типа int, и надо создать массив из 125 элементов типа double. Для этого количество элементов массива надо умножить на размер объекта. Вот только при подсчёте количества элементов легко ошибиться. Поэтому программисты используют специальные макросы, чтобы безопасно вычислять количество элементов. Подробнее зачем и как это делать я неоднократно писал в разных своих статьях (см. здесь упоминание макроса arraysize).

После раскрытия макроса получаются конструкции вида:

template <typename T, size_t N>
char (*RtlpNumberOf( __unaligned T (&)[N] ))[N];
....
size_t s = sizeof(*RtlpNumberOf(liA->Text)) * sizeof(wchar_t);

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

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

Будет ли кому-то полезно все равно выдавать предупреждение? Нет. Это совершенно корректный и надёжно написанный код. Так и надо писать.

Идём дальше. Анализатор выдаст предупреждение V559 на конструкцию вида:

if (a = 5)

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

if ((a = 5))

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

Анализатор PVS-Studio, естественно, тоже промолчит на подобный код.

Быть может, стоило переместить предупреждение на уровень Low, а не полностью подавлять его? Нет.

Есть ли вероятность, что человек случайно поставит лишние круглые скобки вокруг неправильного выражения? Да есть, но крайне маленькая. Вы часто ставите лишние скобки? Не думаю. Скорее это происходит 1 раз на 1000 операторов if. Или даже реже. Соответственно вероятность того, что из-за лишних скобок будет пропущена ошибка, менее 1/1000.

Быть может, лучше всё равно выдавать предупреждение? Нет. Тем самым мы лишим человека «легальной возможности» избежать предупреждения на его коде, но при этом вероятность найти дополнительную ошибку крайне мала.

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

У меня есть вопрос к тем, кто утверждает, что хочет видеть все-все предупреждения. Вы уже покрыли юнит-тестами 100% кода? Нет? Как же так, ведь там могут быть ошибки?!

Сам дам ответ за оппонента. Покрыть 100% кода тестами крайне сложно и дорого. Цена, которая будет заплачена за 100% покрытия, не окупит вложения времени и сил.

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

Давайте рассмотрим ещё один случай, когда не выдается предупреждение V559:

if (ptr = (int *)malloc(sizeof(int) * 100))

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

if (ptr == (int *)malloc(sizeof(int) * 100))

Такое выражение не имеет практического смысла и в добавок приводит к утечке памяти. Так что присваивание внутри условия — это именно то, что и хотел сделать программист.

Будет ли польза от того, если анализатор станет выдавать предупреждения на такие конструкции? Нет.

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

Диагностика V501 — один из лидеров по количеству исключений. Однако, эти исключения не мешают диагностике эффективно работать (proof).

Диагностика выдаёт предупреждения на выражения вида:

if (A == A)
int X = Q - Q;

Если левый и правый операнды идентичны, то это подозрительно.

Одно из исключений гласит, что не стоит выдавать предупреждения, если операция ‘/’ или ‘-‘ применяется к числовым константам. Примеры:

double w = 1./1.;
R[3] = 100 - 100;

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

Пример реального кода с подобными выражениями:

h261e_Clip(mRCqa, 1./31. , 1./1.);

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

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

Возможно, там хотели написать другое выражение? Да, это не исключено. Однако, такие рассуждения — это путь в никуда. Фразу «вдруг хотели написать что-то другое», можно применить и к 1./31. И тут мы приходим к идее идеального анализатора, который просто ругается подряд на все строки в программе. Даже на пустые. Вдруг неправильно, что она пустая. Вдруг там надо было вызвать функцию foo().

Рисунок 8. Нужно уметь остановиться. Иначе полезная прогулка по диагностикам превратится в какую-то фигню.

Рисунок 8. Нужно уметь остановиться. Иначе полезная прогулка по диагностикам превратится в какую-то фигню.

Лучше потерять 1 полезное сообщение, чем при этом показать за компанию ещё 1000 бесполезных. В этом нет ничего ужасного. Полнота выявления ошибок — не единственный критерий полезности анализатора. Не менее важен ещё и баланс между полезными и бесполезными сообщениями. Внимательность быстро теряется. Просматривая отчет с большим количеством ложных срабатываний, человек начинает очень невнимательно относиться к предупреждениям и пропускает многие ошибки, размечая их как не ошибки.

Ещё раз кратко об исключениях

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

Не понимаю, зачем вам жаловаться на непонимание вместо того, чтобы просто сделать функцию и к ней кнопку «вкл/выкл». Хочешь — пользуешься, не хочешь, не нужно — не пользуйся. Да, это работа. Но и да, это ваша работа.

Рисунок 9. Реакция единорога на пожелание сделать настройку, которая отключает всю фильтрацию предупреждений.

Рисунок 9. Реакция единорога на пожелание сделать настройку, которая отключает всю фильтрацию предупреждений.

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

Есть такая кнопка уже в анализаторе! Есть! Она называется «Low» и показывает предупреждения с минимальным уровнем достоверности.

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

Поясню это, опираясь на диагностику V519. Она предупреждает, что одному и тому же объекту дважды подряд присваиваются значения. Пример:

x = 1;
x = 2;

Но только в таком виде диагностика не применима. Поэтому начинаются уточнения, такие как:

Исключение N1. Объект участвует во втором выражении в составе правого операнда операции =.

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

x = A();
x = x + B();

Хочет кто-то посвятить свои силы и время, чтобы просматривать код такого вида? Нет. И убедить в обратном нас не получится.

Главная мысль

У меня нет цели в этой статье кому-то что-то доказать или оправдаться. Её цель направить мысли читателей в правильное русло. Я стараюсь объяснить, что попытка получить как можно больше предупреждений от анализаторов — контрпродуктивна. Это не поможет сделать разрабатываемый проект более надежным, зато отнимет время, которое можно было бы потратить на альтернативные методы повышения качества программы.

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

Приведу аналогию. Безопасности на стройке стараются достичь, используя сочетание различных элементов: обучением технике безопасности, ношением каски, запретом приступать к работе в состоянии алкогольного опьянения и так далее. Неэффективно выбрать только один компонент и надеяться, что он решит все проблемы. Можно сделать чудесную бронированную каску, а лучше шлем, со встроенным счётчиком Гейгера и запасом воды на день. Но всё это не спасет от падения при выполнении высотных работ. Здесь нужно другое устройство — страховочный трос. Можно начать думать в сторону встроенного в каску парашюта. Это, конечно, интересная инженерная задача, но такой подход непрактичен. Очень скоро вес и размер каски превысят разумные пределы. Каска начнет мешаться строителям, злить их, замедлять темп работы. Есть вероятность, что строители вообще начнут тайком снимать каску и работать без неё.

Если пользователь победил все предупреждения анализатора, неразумно стремиться увидеть, как можно больше предупреждений всё более низкого уровня достоверности. Будет полезнее заняться юнит-тестами и довести покрытие кода, скажем до 80%. Стремиться к 100% покрытию я не призываю, так как время, которое потребуется на реализацию 100% покрытия и его поддержания, перевесит пользу от этого действия. Далее можно добавить в процесс тестирования один из динамических анализаторов кода. Некоторые виды дефектов, которые находят динамические анализаторы, не могут найти статические анализаторы. И наоборот. Поэтому динамический и статический анализ отлично дополняют друг друга. Можно развивать UI тесты.

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

На самом деле я думаю, что все, кто пишет, что хочет ещё больше неотфильтрованных сообщений от статических анализаторов кода, никогда этими самыми анализаторами кода не пользовались. Или пробовали их на игрушечных проектах, в которых низкая плотность ошибок. В любом настоящем проекте всегда стоит проблема, как разобраться с имеющимися ложными срабатываниями. Это большая сложная задача, над которой приходится работать как разработчикам анализаторов, так и их пользователям. Куда уж ещё больше предупреждений?!

Мы регулярно получаем от клиентов письма, где они просят устранить то или иное ложное срабатывание. А вот «дайте больше сообщений» мы ещё ни разу не слышали.

Заключение

Из этой статьи мы узнали:

  1. Анализатор PVS-Studio старается искать не «запахи», а настоящие ошибки, которые могут привести к неправильной работе программы.
  2. Диагностические сообщения разделяются на три уровня достоверности (High, Medium, Low).
  3. Мы рекомендуем к изучению только уровни High и Medium.
  4. Для тех, кто волновался, что исключения могут удалить полезную ошибку: это маловероятно. Скорее всего, такое недостоверное предупреждение перемещено на уровень Low. Можно открыть вкладку Low и изучать такие предупреждения.
  5. Исключения в диагностиках неизбежны, иначе инструмент начнет больше мешать, чем помогать.

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

Picture 11

Единорог и дальше будет стоять на страже качества программного кода. Желаю всем удачи и приглашаю дополнительно познакомиться с презентацией «PVS-Studio 2017».

Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Andrey Karpov. The way static analyzers fight against false positives, and why they do it

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

На самом деле, «вранье» глюкометра — вполне возможная вещь, причинами которой могут выть ошибки в эксплуатации прибора, ведь не зря в комплекте с глюкометрами поставляются подробные солидные инструкции по использованию гаджета!

Чтобы глюкометр не ошибался, а вам не приходилось переводить драгоценные полоски для повторных измерений, читайте наш материал о причинах «обмана».

Топ причин, по которым глюкометр может показывать ложные результаты:

Соблюдайте условия хранения тест-полосок!

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

Читайте инструкцию к глюкометру

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

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

Калибруйте глюкометр и регулярно проверяете его тестовым раствором

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

Вымойте руки перед анализом и вытрите их насухо!

Вы забыли помыть руки или, наоборот, помыли, но забыли вытереть насухо — получите неверный результат. В первом случае ваша кровь может смешаться с частичками глюкозы на пальцах, оставшимися от продукта — достаточно, например, съесть сочное яблоко, и, не помыв после этого руки, измерить сахар. +5 — 10 ммоль к реальному результату гарантированно! Во втором случае ваша кровь просто-напросто разбавляется водой, следовательно, концентрация глюкозы уменьшается.

Любой глюкометр имеет допустимую погрешность

Вы замеряете сахар крови несколько раз подряд, видите разные результаты, и уже задумываетесь над тем, чтобы купить прибор другой марки? Все приборы имеют допустимую погрешность в 15-20 %. То есть, при реальном сахаре крови 5 ммоль, глюкометр имеет право показать вам любую цифру в диапазоне от 4 до 6 ммоль! Чем выше сахар — тем больше разброс, например, при реальных 15 ммоль, разброс ск по глюкоетру может быть от 12 до 18 ммоль. 

Используйте глюкометр аккуратно

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

Не забывайте чистить ваш глюкометр!

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

У всего есть свой срок годности

Может быть ваш прибор уже отработал свое и ему пора на пенсию?

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

Купить глюкометр и тест-полоски на любой вкус и кошелек вы всегда можете в нашем интернет-магазине ДиаМарка:

Понравилась статья? Поделить с друзьями:
  • Ошибка амт гранта
  • Ошибка амортизатора лазерного датчика расстояния dream d9
  • Ошибка амми админ 12007
  • Ошибка ами админ 12007
  • Ошибка американ мегатрендс что делать