Скачать презентацию
Идет загрузка презентации. Пожалуйста, подождите
Презентация была опубликована 10 лет назад пользователемВячеслав Стрекалов
1 Статический анализ Си++ кода Карпов Андрей Николаевич к.ф.-м.н., технический директор ООО «Системы программной верификации»
2 О чем доклад Мы все допускаем ошибки при программировании и тратим массу времени на их устранение. Один из методов который позволяет быстро диагностировать дефекты – статический анализ исходного кода.
3 «Надо сразу писать хороший код» - не работает на практике! даже лучшие программисты ошибаются и делают опечатки; далее - ряд примеров ошибок, обнаруженных статическим анализатором кода в известных проектах; для анализа использовался инструмент PVS-Studio.
4 Приоритет операций & и ! Return to Castle Wolfenstein - компьютерная игра, шутер от первого лица, разработанный компанией id Software. Движок игры распространяется по GPL лицензии. #define SVF_CASTAI 0x if ( !ent->r.svFlags & SVF_CASTAI ) if ( ! (ent->r.svFlags & SVF_CASTAI) )
5 Использование && вместо & #define REO_INPLACEACTIVE (0x L) #define REO_OPEN (0x L) if (reObj.dwFlags && REO_INPLACEACTIVE) m_pRichEditOle->InPlaceDeactivate(); if(reObj.dwFlags && REO_OPEN) hr = reObj.poleobj->Close(OLECLOSE_NOSAVE); Stickies - желтые клеящиеся бумажки, только на мониторе.
6 Undefined behavior while (*(n = ++s + strspn(s, EZXML_WS)) && *n != '>') { Miranda IM (Miranda Instant Messenger) - программа мгновенного обмена сообщениями для Microsoft Windows.
7 Использование delete для массива auto_ptr child_array(new VARIANT[child_count]); ~auto_ptr() { delete _Myptr; } Chromium - веб-браузер с открытым исходным кодом, разработанный компанией Google. На основе Chromium создаётся браузер Google Chrome. Использовать auto_ptr для массивов нельзя. В деструкторе auto_ptr уничтожается только один элемент: В качестве альтернативы, например, можно использовать boost::scoped_array.
8 Всегда истинное условие WinDjView - быстрая и компактная программа для просмотра файлов формата DjVu. inline bool IsValidChar(int c) { return c == 0x9 || 0xA || c == 0xD || c >= 0x20 && c = 0xE000 && c = 0x10000 && c
9 Оформление кода отличается от его логики if(pushval != 0) if(pushval) v->GetUp(-1) = t; else v->Pop(1); Squirrel - интерпретируемый язык программирования, разработанный специально для использования в качестве скриптового языка в приложениях реального времени, таких как компьютерные игры. v->Pop(1); - никогда не вызывается
10 Случайное объявление локальной переменной FCE Ultra – открытый эмулятор приставки Nintendo Entertainment System int iNesSaveAs(char* name) {... fp = fopen(name,"wb"); int x = 0; if (!fp) int x = 1;... }
11 Работа с char как с unsigned char // check each line for illegal utf8 sequences. // If one is found, we treat the file as ASCII, // otherwise we assume an UTF8 file. char * utf8CheckBuf = lineptr; while ((bUTF8)&&(*utf8CheckBuf)) { if ((*utf8CheckBuf == 0xC0)|| (*utf8CheckBuf == 0xC1)|| (*utf8CheckBuf >= 0xF5)) { bUTF8 = false; break; } TortoiseSVN клиент для системы контроля версий Subversion, выполненный как расширение оболочки Windows.
12 Случайные восьмеричные числа oCell._luminance = uint16(0.2220f*iPixel._red f*iPixel._blue f*iPixel._green);.... oCell._luminance = 2220*iPixel._red *iPixel._blue *iPixel._green; eLynx Image Processing SDK and Lab
13 Одна переменная для двух циклов static int i,j,k,l,m;... for(j=0; j
14 Выход за границы массива #define SBMAX_l 22 int l[1+SBMAX_l]; for (r0 = 0; r0 < 16; r0++) {... for (r1 = 0; r1 < 8; r1++) { int a2 = gfc->scalefac_band.l[r0 + r1 + 2]; LAME - свободное приложение для кодирования аудио в формат MP3.
15 Приоритет операций * и ++ STDMETHODIMP CCustomAutoComplete::Next(..., ULONG *pceltFetched) {... if (pceltFetched != NULL) *pceltFetched++;... } (*pceltFetched)++; eMule - это клиент для сети обмена файлами ED2K.
16 Ошибка в сравнении BUFFERTYPE m_nBufferType[2];... // Handle unnamed buffers if ((m_nBufferType[nBuffer] == BUFFER_UNNAMED) || (m_nBufferType[nBuffer] == BUFFER_UNNAMED)) nSaveErrorCode = SAVE_NO_FILENAME; WinMerge свободное ПО с открытым исходным кодом для сравнения и синхронизации файлов и директорий. Если посмотреть код рядом, то по аналогии здесь должно быть: (m_nBufferType[0] == BUFFER_UNNAMED) || (m_nBufferType[1] == BUFFER_UNNAMED)
17 Забытый индекс массива IPP Samples - примеры, демонстрирующие работу с библиотекой Intel Performance Primitives Library 7.0. void lNormalizeVector_32f_P3IM(..., Ipp32s* mask,...) { Ipp32s i; Ipp32f norm; for(i=0; i
18 Одинаковые ветви кода Notepad++ - свободный текстовый редактор для Windows с подсветкой синтаксиса большого количества языков программирования и разметки. if (!_isVertical) Flags |= DT_VCENTER; else Flags |= DT_BOTTOM; if (!_isVertical) Flags |= DT_BOTTOM; else Flags |= DT_BOTTOM;
19 Вызов неверной функции со схожим именем /** Deletes all previous field specifiers. * This should be used when dealing * with clients that send multiple NEP_PACKET_SPEC * messages, so only the last PacketSpec is taken * into account. */ int NEPContext::resetClientFieldSpecs(){ this->fspecs.empty(); return OP_SUCCESS; } /* End of resetClientFieldSpecs() */ Какой замечательный комментарий. Жаль только не то делаем, что хотим. Nmap Security Scanner - свободная утилита, предназначенная для разнообразного настраиваемого сканирования IP-сетей с любым количеством объектов, определения состояния объектов сканируемой сети.
20 Опасный оператор ?: Newton Game Dynamics - популярный физический движок, который предоставляет надежное и быстрое решение для симуляции физического поведения объектов окружающей среды. den = dgFloat32 (1.0e-24f) * (den > dgFloat32(0.0f)) ? dgFloat32(1.0f) : dgFloat32(-1.0f); Приоритет оператора ?: ниже, чем у оператора умножения *.
21 И так далее, и так далее… if (m_szPassword != NULL) { if (m_szPassword != '\0') { if (*m_szPassword != '\0') Библиотека Ultimate TCP/IP bleeding = 0; bleedx = 0,bleedy; direction = 0; Lugaru bleedx = 0; bleedy = 0;
22 И так далее, и так далее… FCE Ultra if((t=(char *)realloc( next->name, strlen(name+1)))) if((t=(char *)realloc( next->name, strlen(name)+1))) minX=max(0,minX+mcLeftStart-2); minY=max(0,minY+mcTopStart-2); maxX=min((int)width,maxX+mcRightEnd-1); maxY=min((int)height,maxX+mcBottomEnd-1); minX=max(0,minX+mcLeftStart-2); minY=max(0,minY+mcTopStart-2); maxX=min((int)width,maxX+mcRightEnd-1); maxY=min((int)height,maxY+mcBottomEnd-1);
23 Низкоуровневые операции работы с памятью ZeroMemory; memset; memcpy; memcmp; … Хочется отдельно остановиться на наследии программ на Си, где использовались функции:
24 Низкоуровневые операции работы с памятью ID_INLINE mat3_t::mat3_t( float src[3][3] ) { memcpy( mat, src, sizeof( src ) ); } Return to Castle Wolfenstein itemInfo_t *itemInfo; memset( itemInfo, 0, sizeof( &itemInfo ) ); memset( itemInfo, 0, sizeof( *itemInfo ) ); ID_INLINE mat3_t::mat3_t( float (&src)[3][3] ) { memcpy( mat, src, sizeof( src ) ); }
25 Низкоуровневые операции работы с памятью CxImage - открытая библиотека обработки изображений. memset(tcmpt->stepsizes, 0, sizeof(tcmpt->numstepsizes * sizeof(uint_fast16_t))); memset(tcmpt->stepsizes, 0, tcmpt->numstepsizes * sizeof(uint_fast16_t));
26 Низкоуровневые операции работы с памятью dgInt32 faceOffsetHitogram[256]; dgSubMesh* mainSegmenst[256]; memset (faceOffsetHitogram, 0, sizeof (faceOffsetHitogram)); memset (mainSegmenst, 0, sizeof (faceOffsetHitogram)); Скопировали код и не полностью поправили. В результате в Win64 размер указателя станет не равен размеру типа dgInt32 и мы очистим только часть массива mainSegmenst. Красивый пример 64-битной ошибки:
27 Низкоуровневые операции работы с памятью #define CONT_MAP_MAX 50 int _iContMap[CONT_MAP_MAX];... memset(_iContMap, -1, CONT_MAP_MAX); memset(_iContMap, -1, CONT_MAP_MAX * sizeof(int));
28 Низкоуровневые операции работы с памятью Да, сейчас это не ошибка. Но это мина! Real w, x, y, z;... inline Quaternion(Real* valptr) { memcpy(&w, valptr, sizeof(Real)*4); } OGRE (Object-Oriented Graphics Rendering Engine) - объектно-ориентированный графический движок с открытым исходным кодом, написанный на C++.
29 Чем раньше – тем лучше
30 Почему все-таки не только юнит-тесты? проверка мест, редко получающих управления; обнаружение плавающих ошибок (undefined behavior, гейзенбаги); не на все варианты кода можно написать юнит-тест: – сложные счетные алгоритмы; – интерфейс.
31 Здесь не поможет юнит-тест, но поможет статический анализ OPENFILENAME lofn;... lofn.lpstrFilter = uni("All Files (*.*)\0*.*"); Fennec Media Project - универсальный медиа- плеер ориентированный на воспроизведение аудио и видео в высоком разрешении. lofn.lpstrFilter = uni("All Files (*.*)\0*.*\0");
32 Здесь не поможет юнит-тест, но поможет статический анализ static INT_PTR CALLBACK DlgProcTrayOpts(...) {... EnableWindow(GetDlgItem(hwndDlg,IDC_PRIMARYSTATUS),TRUE); EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIMESPIN),FALSE); EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIME),FALSE); EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSPRIMARY),FALSE); EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLE),FALSE); EnableWindow(GetDlgItem(hwndDlg,IDC_MULTITRAY),FALSE);... }
33 Где подробнее узнать про PVS-Studio? PVS-Studio - статический анализатор, выявляющий ошибки в исходном коде приложений на языке C/C++/C++0x. Страница продукта: Демонстрационная версия: download/ download/ Документация на русском языке: PVS-Studio интегрируется в среду разработки Visual Studio 2005/2008/2010.
34 Вопросы ? Контактная информация: Карпов Андрей Николаевич к.ф.-м.н., технический директор ООО «Системы программной верификации» Сайт: Тел.: +7 (4872) (GMT + 03:00) Twitter:
Еще похожие презентации в нашем архиве:
© 2024 MyShared Inc.
All rights reserved.