SlideShare una empresa de Scribd logo
1 de 10
Descargar para leer sin conexión
64-битная версия Loki
Авторы: Евгений Рыжков, Андрей Карпов, Андрей Александреску, Питер Кюмель, Рич Спозато,

Дата: 25.09.2009


Аннотация
Статья представляет собой отчет о проверки библиотеки Loki на совместимость с 64-битными
системами с помощью анализатора кода Viva64 компании ООО "СиПроВер". Содержатся
рекомендации пользователям библиотеки. Статья будет полезна также пользователям других
библиотек, построенных на шаблонах, так как раскрывает особенности анализа подобных
библиотек.


Введение
Библиотека Loki разработана Андреем Александреску как часть книги "Современное
проектирование на С++: Обобщенное программирование и прикладные шаблоны
проектирования". Аннотация к книге гласит: "В книге изложена новая технология
программирования, представляющая собой сплав обобщенного программирования,
метапрограммирования шаблонов и объектно-ориентированного программирования на C++.
Настраиваемые компоненты, созданные автором, высоко подняли уровень абстракции, наделив
язык C++ чертами языка спецификации проектирования, сохранив всю его мощь и
выразительность".

Компания ООО "СиПроВер", создающая анализатор кода Viva64 для разработки 64-битных
приложений, активно общается с авторами различных программных проектов. Однажды к нам
обратился Рич Спозато (Rich Sposato), один из администраторов проекта Loki, и попросил
проверить код библиотеки на предмет совместимости с 64-битными системами с помощью
нашего инструмента Viva64. Мы сразу же согласились. Ведь это не только возможность принести
пользу сообществу разработчиков, но и настоящий "тест выносливости" для нашего анализатора
кода Viva64. Всем известно, что библиотека Loki написана с применением самых современных и
мощных возможностей языка Си++. И если анализатор Viva64 справится с Loki, то и другие более
простые проекты не вызовут никаких проблем.

Надо заметить, что данная статья основана на версии Loki от мая 2009 года (новее, чем
официальная на тот момент версия Loki 0.1.7), поэтому в более новых версиях Loki указанные
проблемы будут устранены.

Итак, мы скачали последнюю версию Loki из SVN-репозитория и приступили к работе.


Сборка 64-битной Loki в Microsoft Visual Studio 2005
Анализатор кода Viva64 интегрируется в среду разработки Microsoft Visual Studio, поэтому
разумно было собрать версию Loki именно для этой среды. В составе пакета Loki есть готовые
файлы решений для Visual Studio 2005 и Visual Studio 2008. Однако на момент мая 2009 года эти
решения содержат лишь 32-битные конфигурации. Поэтому необходимо в Visual Studio создать
конфигурации для платформы x64. Добавив нужные конфигурации можно запустить компиляцию
64-битной версии.

Библиотека Loki предназначена для работы на большом количестве различных платформ и
собирается с помощью многих наиболее известных компиляторов. Именно поэтому 64-битная
версия Loki скомпилировалась практически сразу же. Из 20 проектов, входящих в решение, не
собрался только один:

========== Build: 19 succeeded, 1 failed, 0 up-to-date, 0 skipped
==========

Это был проект SafeFormat:

16>------ Build started: Project: SafeFormat, Configuration: Debug x64
------

16>Compiling...

16>main.cpp

16>.main.cpp(255) : error C3066: there are multiple ways

that an object of this type can be called with these arguments

16>        ....includeloki/SafeFormat.h(109): could be
'Loki::PrintfState<Device,Char>

&Loki::PrintfState<Device,Char>::operator ()(bool)'

...

16>           while trying to match the argument list '(UInt)'

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

void test_dword()

{

      typedef signed int Int;

      typedef unsigned int UInt;

      typedef signed long Long;

      typedef unsigned long ULong;

      Int i(0);

      UInt ui(0);

      Long l(0);

      ULong ul(0);

      Printf("%d")(i);
Printf("%d")(ui); // Проблема в этой строке

     Printf("%d")(l);

     Printf("%d")(ul);

}

Printf - это функция, внутри которой используется макрос LOKI_PRINTF_STATE_FORWARD. С
помощью этого макроса задается ряд вспомогательных функций. В нем-то и кроется проблема.
Внутри файла SafeFormat.h вместо следующего фрагмента:

#if (defined(_WIN32) || defined(_WIN64))

          LOKI_PRINTF_STATE_FORWARD(unsigned long)

#else

необходимо написать так:

#if (defined(_WIN32) || defined(_WIN64))

#if (defined(_WIN64))

          LOKI_PRINTF_STATE_FORWARD(unsigned int)

#endif

          LOKI_PRINTF_STATE_FORWARD(unsigned long)

#else

После этого исправления ошибка компиляции пропадет и все 20 проектов библиотеки
скомпилируются.

Однако среди прочих диагностических сообщений (warnings) компилятора мы видим сообщение,
касающееся 64-битного кода:

2>.CachedFactoryTest.cpp(204) : warning C4267: 'argument' :

conversion from 'size_t' to 'const int', possible loss of data

2>          .CachedFactoryTest.cpp(238) : see reference to function
template

instantiation 'milliSec typicalUse<Cache>

(Cache &,unsigned int,unsigned int,unsigned int)' being compiled

2>          with

2>          [

2>                Cache=CRandomEvict

2>          ]
2>           .CachedFactoryTest.cpp(252) : see reference to function
template

instantiation 'void displayTypicalUse<CRandomEvict>

(Cache &,unsigned int,unsigned int,unsigned int)' being compiled

2>           with

2>           [

2>                Cache=CRandomEvict

2>           ]

Это сообщение говорит о потенциально опасном преобразовании типа size_t внутри функции
typicalUse() в файле CachedFactoryTest.cpp:

// Registering objects

for(size_t i=0;i<objectKind;i++)

  CC.Register(i, createProductNull);

Граница цикла (переменная objectKind) представлена типом unsigned. Поэтому использовать для
счетчика цикла переменную типа size_t не имеет смысла. После исправления типа счетчика цикла
проблема исчезнет:

 // Registering objects

for(unsigned i=0;i<objectKind;i++)

  CC.Register(i, createProductNull);

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


Проверка 64-битной Loki с помощью Viva64
Для того чтобы убедится в совместимости Loki с 64-битными системами, выполним анализ кода с
помощью Viva64. Анализатор кода Viva64 предназначен для разработки новых 64-битных
приложений и для миграций существующих 32-битных на 64-битную платформу.

Запуск Viva64 для анализа Loki выявил список из 89 потенциально-опасных синтаксических
конструкций. Это не значит, что в библиотеке Loki содержится 89 ошибок, связанных с 64-битным
кодом. Но все эти 89 мест должен просмотреть разработчик для того, чтобы понять,
действительно ли там возможна ошибка или нет. Разумеется, мы проанализировали эти ошибки.

1 Некорректно используемая константа LONG_MIN
Начнем с ошибки, связанной с некорректно используемой константой LONG_MIN в следующей
функции:
char* RenderWithoutSign(LOKI_SAFEFORMAT_SIGNED_LONG n,

      char* bufLast, unsigned int base, bool uppercase)

Она находится в файле SafeFormat.h. Проблема в строке:

if (n != LONG_MIN) {

Тип LOKI_SAFEFORMAT_SIGNED_LONG объявляется как тип, способный вмещать 64-битные
значения в 64-битной системе. В Unix-системах (с моделью данных LP64) для этого используют тип
long. Но в 64-битных Windows-системах (модель данных LLP64) тип long остался 32-битным.
Поэтому в Loki тип LOKI_SAFEFORMAT_SIGNED_LONG объявлен так:

#if defined(_WIN32) || defined(_WIN64)

    #define LOKI_SAFEFORMAT_SIGNED_LONG intptr_t

    #define LOKI_SAFEFORMAT_UNSIGNED_LONG uintptr_t

#else

    #define LOKI_SAFEFORMAT_SIGNED_LONG signed long

    #define LOKI_SAFEFORMAT_UNSIGNED_LONG unsigned long

#endif

Поскольку тип long в 64-битных Windows-системах остался 32-битным, то и константа LONG_MIN
задает минимальное значение 32-битной переменной. А это значит, что ее использование
некорректно при работе с 64-битными типами (в нашем случае с intptr_t). Решением будет
использование собственной константы. Например, исправление может выглядеть так:

#if defined(_WIN32) || defined(_WIN64)

#   define LOKI_SAFEFORMAT_SIGNED_LONG intptr_t

#if defined(_WIN64)

#   define LOKI_SAFEFORMAT_SIGNED_LONG_MIN_VALUE LLONG_MIN

#   define LOKI_SAFEFORMAT_SIGNED_LONG_MAX_VALUE LLONG_MAX

#else

#   define LOKI_SAFEFORMAT_SIGNED_LONG_MIN_VALUE LONG_MIN

#   define LOKI_SAFEFORMAT_SIGNED_LONG_MAX_VALUE LONG_MAX

#endif

...

#else

#   define LOKI_SAFEFORMAT_SIGNED_LONG signed long

#   define LOKI_SAFEFORMAT_SIGNED_LONG_MIN_VALUE LONG_MIN
#   define LOKI_SAFEFORMAT_SIGNED_LONG_MAX_VALUE LONG_MAX

...

#endif

И, соответственно, строку

if (n != LONG_MIN) {

надо заменить на строку

if (n != LOKI_SAFEFORMAT_SIGNED_LONG_MIN_VALUE) {

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

2 Некоторые виды магических чисел - ошибка или нет?
Одной из проблем, выявляемой анализатором Viva64 являются магические числа. С точки зрения
миграции кода с 32-битной на 64-битную платформу есть ряд чисел, использование которых
наиболее опасно. Возможно, где-то в коде программист рассчитывает на определенный размер
типа данных, что может вызвать проблему. Те, кто смотрят на сообщения от анализаторов кода,
часто жалуются на бессмысленность подобных сообщений. Действительно, какой смысл ругаться
анализатору кода на число 4 в подобных строках:

::Loki::ScopeGuard guard4 = ::Loki::MakeGuard( &HasFour, 1, 2, 3, 4 );

::Loki::ScopeGuard guard5 = ::Loki::MakeGuard( &HasFive, 1, 2, 3, 4, 5
);

Но бывают такие конструкции, которые надо анализировать очень тщательно. Например, в файле
SafeFormatmain.cpp видим код:

case 'X':

      // TestCase(formatSpec, RandomInt(-10000, 10000));

      // don't test negative values on 64bit systems, because

      // snprintf does not support 64 Bit values

      TestCase(formatSpec,

          RandomInt( -10000 * (sizeof(size_t)>4 ? 0 : 1) , 10000));

      break;

case 'e':

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

3 Прибавление int к указателю - потенциальная проблема
Файл flexsimplestringstorage.h содержит функцию:

void resize(size_type newSize, E fill)
{

    const int delta = int(newSize - size());

    if (delta == 0) return;

    if (delta > 0)

    {

        if (newSize > capacity())

        {

            reserve(newSize);

        }

        E* e = &*end();

        flex_string_details::pod_fill(e, e + delta, fill);

    }

    pData_->pEnd_ = pData_->buffer_ + newSize;

}

Анализатор Viva64 сообщает о потенциальной проблеме здесь:

flex_string_details::pod_fill(e, e + delta, fill);

Недостаток кода заключается в том, что к указателю e прибавляется переменная delta типа int. Это
потенциальная проблема, так как функция pod_fill не сможет обрабатывать объем данных более
двух гигабайт (INT_MAX символов). Конечно же, конкретно здесь ошибки, видимо, нет, поскольку
вряд ли бывают строки более двух гигабайт. Но лучше все-таки заменить тип переменной delta с
int на ptrdiff_t:

const ptrdiff_t delta = ptrdiff_t(newSize - size());

4 Использование int для индексации массивов некорректно
Для доступа к большим массивам данным (более INT_MAX элементов) надо использовать типы
ptrdiff_t или size_t. В файле SmallObjSmallObjBench.cpp присутсвует довольно большой макрос
LOKI_SMALLOBJ_BENCH_ARRAY, в котором работа с массивом ведется через индексацию по int.
Хотя это лучше исправить, в данном месте это не является ошибкой.

5 Правильные аргументы функций
Внутри файла CachedFactoryCachedFactoryTest.cpp объявлена функция:

template< class Cache >

milliSec typicalUse(Cache &CC, unsigned objectKind,

                           unsigned maxObjectCount, unsigned maxIteration)
Для параметра objectKind лучше использовать тип size_t. Но поскольку этот код относится к
тестам, то какой-либо серьезного недостатка в этом нет.


Библиотека Loki совместима с 64-битными системами - значит
программа, использующая ее также совместима?
Все немногие обнаруженные проблемы библиотеки Loki, перечисленные ранее, легко исправимы.
Значит ли это, что если в Loki нет никаких 64-битных проблем (а это именно так), то и приложение,
использующее эту библиотеку, безопасно с точки зрения 64-битного кода? К сожалению нет!

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

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

template <class T>

struct TClass

{

    int m_a;

    T m_b;

    int m_c;

};

Если здесь T имеет тип int, то структура оптимальна. Если же T имеет тип size_t, то структура
займет 24 байта, вместо возможных 16 байтах. Тогда в случае большого количества подобных
объектов лучше было бы переписать:

template <class T>

struct TClass

{

    T m_b;

    int m_a;

    int m_c;

};

Но проверить это анализатор может только выполнив инстанцирование шаблона. То есть имея
лишь объявление класса в заголовке выявит проблему нельзя.

Другой пример, опять же не относящийся к Loki, связанный с приведением типов:

template<typename T1, typename T2>
class TemplateClass

{

public:

          void test1()

          {

                     m_a.m_value = m_b.m_value; // Есть ли здесь ошибка?

          }

private:

          T1 m_a;

          T2 m_b;

};

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

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

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


Выводы
По результатам работы сотрудников компании ООО "СиПроВер" над проверкой на совместимость
с 64-бибтными системами библиотеки Loki сделаны следующие выводы:

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

Анализатор кода Viva64, предназначенный для разработки новых 64-битных и миграции старых
32-битных приложений показал себя очень хорошо при проверке сложного шаблонного кода
библиотеки. Это говорит о высоком качестве анализатора кода.
Хотя библиотека Loki и не содержит 64-битных проблем, они возможны в пользовательских
приложениях, использующих Loki. Поскольку конечный код зависит от того, с какими
параметрами инстанцировались шаблоны, то обязательно надо проверять пользовательские
приложения анализатором кода. Только тогда можно быть уверенным в полной совместимости
приложения с 64-битными системами.


Благодарность
Благодарим всех, кто принимал участие в анализе библиотеки Loki и в оценке этой работы в
команде Loki:

   •   Спасибо компании ООО "СиПроВер", которая проанализировала код библиотеки Loki и
       выполнила верификацию ее для работы в 64-битном режиме, в частности: Андрею
       Карпову и Евгению Рыжкову.
   •   Спасибо команде Loki: Андрею Александреску, Питеру Кюмелю, Ричу Спозато за
       совместную работу над проверкой и редактированием статьи, а также ценные замечания.
   •   Спасибо Ричу Спозато, за координирование всей работы.


Библиографический список
   1. Библиотека Loki. http://www.viva64.com/go.php?url=515.
   2. Анализатор кода Viva64. http://www.viva64.com/viva64-tool.

Más contenido relacionado

La actualidad más candente

Погружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьПогружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьYauheni Akhotnikau
 
Построение компилятора на базе LLVM — Павел Сычев
 Построение компилятора на базе LLVM — Павел Сычев Построение компилятора на базе LLVM — Павел Сычев
Построение компилятора на базе LLVM — Павел СычевYandex
 
Архитектура компилятора Swift
Архитектура компилятора SwiftАрхитектура компилятора Swift
Архитектура компилятора SwiftAndrey Volobuev
 
C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.Igor Shkulipa
 
Сущность библиотеки анализа кода VivaCore
Сущность библиотеки анализа кода VivaCoreСущность библиотеки анализа кода VivaCore
Сущность библиотеки анализа кода VivaCoreTatyanazaxarova
 
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...Stfalcon Meetups
 
Статический анализ Си++ кода и новый стандарт языка C++0x
Статический анализ Си++ кода и новый стандарт языка C++0xСтатический анализ Си++ кода и новый стандарт языка C++0x
Статический анализ Си++ кода и новый стандарт языка C++0xTatyanazaxarova
 
Теория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямТеория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямSergey Staroletov
 
C++ Core Guidelines
C++ Core Guidelines C++ Core Guidelines
C++ Core Guidelines Sergey Zubkov
 
Candidates for-php-developers-tests
Candidates for-php-developers-testsCandidates for-php-developers-tests
Candidates for-php-developers-testsguest5fa21c
 
Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
 Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ... Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...Yandex
 
C++ осень 2013 лекция 6
C++ осень 2013 лекция 6C++ осень 2013 лекция 6
C++ осень 2013 лекция 6Technopark
 
Иван Кочуркин. Теория и практика парсинга формальных языков
Иван Кочуркин. Теория и практика парсинга формальных языковИван Кочуркин. Теория и практика парсинга формальных языков
Иван Кочуркин. Теория и практика парсинга формальных языковMskDotNet Community
 
Андрей Карпов, Приватные байки от разработчиков анализатора кода
Андрей Карпов, Приватные байки от разработчиков анализатора кодаАндрей Карпов, Приватные байки от разработчиков анализатора кода
Андрей Карпов, Приватные байки от разработчиков анализатора кодаSergey Platonov
 
C++ осень 2013 лекция 2
C++ осень 2013 лекция 2C++ осень 2013 лекция 2
C++ осень 2013 лекция 2Technopark
 
C# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущееC# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущееGetDev.NET
 
Как жить в согласии с SOLID?
Как жить в согласии с SOLID?Как жить в согласии с SOLID?
Как жить в согласии с SOLID?DotNetConf
 

La actualidad más candente (20)

Погружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная частьПогружение в SObjectizer 5.5. Вводная часть
Погружение в SObjectizer 5.5. Вводная часть
 
лекция 4
лекция 4лекция 4
лекция 4
 
Построение компилятора на базе LLVM — Павел Сычев
 Построение компилятора на базе LLVM — Павел Сычев Построение компилятора на базе LLVM — Павел Сычев
Построение компилятора на базе LLVM — Павел Сычев
 
Архитектура компилятора Swift
Архитектура компилятора SwiftАрхитектура компилятора Swift
Архитектура компилятора Swift
 
New Android NDK & JNI
New Android NDK & JNINew Android NDK & JNI
New Android NDK & JNI
 
C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.C++ STL & Qt. Занятие 06.
C++ STL & Qt. Занятие 06.
 
Сущность библиотеки анализа кода VivaCore
Сущность библиотеки анализа кода VivaCoreСущность библиотеки анализа кода VivaCore
Сущность библиотеки анализа кода VivaCore
 
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...
Использование Java Native Interface (JNI) и кросплатформенных C/C++ реализаци...
 
Статический анализ Си++ кода и новый стандарт языка C++0x
Статический анализ Си++ кода и новый стандарт языка C++0xСтатический анализ Си++ кода и новый стандарт языка C++0x
Статический анализ Си++ кода и новый стандарт языка C++0x
 
Теория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциямТеория языков программирования некоторые слайды к лекциям
Теория языков программирования некоторые слайды к лекциям
 
C++ Core Guidelines
C++ Core Guidelines C++ Core Guidelines
C++ Core Guidelines
 
Candidates for-php-developers-tests
Candidates for-php-developers-testsCandidates for-php-developers-tests
Candidates for-php-developers-tests
 
Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
 Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ... Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
Использование C++ для низкоуровневой платформозависимой разработки — Кирилл ...
 
C++ осень 2013 лекция 6
C++ осень 2013 лекция 6C++ осень 2013 лекция 6
C++ осень 2013 лекция 6
 
Иван Кочуркин. Теория и практика парсинга формальных языков
Иван Кочуркин. Теория и практика парсинга формальных языковИван Кочуркин. Теория и практика парсинга формальных языков
Иван Кочуркин. Теория и практика парсинга формальных языков
 
Андрей Карпов, Приватные байки от разработчиков анализатора кода
Андрей Карпов, Приватные байки от разработчиков анализатора кодаАндрей Карпов, Приватные байки от разработчиков анализатора кода
Андрей Карпов, Приватные байки от разработчиков анализатора кода
 
C++ осень 2013 лекция 2
C++ осень 2013 лекция 2C++ осень 2013 лекция 2
C++ осень 2013 лекция 2
 
JavaScript Intro
JavaScript IntroJavaScript Intro
JavaScript Intro
 
C# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущееC# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущее
 
Как жить в согласии с SOLID?
Как жить в согласии с SOLID?Как жить в согласии с SOLID?
Как жить в согласии с SOLID?
 

Destacado

Akademy es2010 bugbuster_rafael_fernandez
Akademy es2010 bugbuster_rafael_fernandezAkademy es2010 bugbuster_rafael_fernandez
Akademy es2010 bugbuster_rafael_fernandezAkademyEs2010
 
Akademy es2010 cifrado_html5_eduardo_robles
Akademy es2010 cifrado_html5_eduardo_roblesAkademy es2010 cifrado_html5_eduardo_robles
Akademy es2010 cifrado_html5_eduardo_roblesAkademyEs2010
 
Revista ips 2 q noviembre
Revista ips 2 q noviembreRevista ips 2 q noviembre
Revista ips 2 q noviembreipsadmin
 
Akademy es2010 desktop4all_xavier_gonzalez
Akademy es2010 desktop4all_xavier_gonzalezAkademy es2010 desktop4all_xavier_gonzalez
Akademy es2010 desktop4all_xavier_gonzalezAkademyEs2010
 
Revista ips 1 qjunio
Revista ips 1 qjunioRevista ips 1 qjunio
Revista ips 1 qjunioipsadmin
 
Tp De Informatico.Rodri
Tp De Informatico.RodriTp De Informatico.Rodri
Tp De Informatico.Rodrirodrigoalarcon
 

Destacado (8)

Akademy es2010 bugbuster_rafael_fernandez
Akademy es2010 bugbuster_rafael_fernandezAkademy es2010 bugbuster_rafael_fernandez
Akademy es2010 bugbuster_rafael_fernandez
 
Akademy es2010 cifrado_html5_eduardo_robles
Akademy es2010 cifrado_html5_eduardo_roblesAkademy es2010 cifrado_html5_eduardo_robles
Akademy es2010 cifrado_html5_eduardo_robles
 
Tp3 martin torres
Tp3 martin torresTp3 martin torres
Tp3 martin torres
 
Revista ips 2 q noviembre
Revista ips 2 q noviembreRevista ips 2 q noviembre
Revista ips 2 q noviembre
 
Blog
Blog          Blog
Blog
 
Akademy es2010 desktop4all_xavier_gonzalez
Akademy es2010 desktop4all_xavier_gonzalezAkademy es2010 desktop4all_xavier_gonzalez
Akademy es2010 desktop4all_xavier_gonzalez
 
Revista ips 1 qjunio
Revista ips 1 qjunioRevista ips 1 qjunio
Revista ips 1 qjunio
 
Tp De Informatico.Rodri
Tp De Informatico.RodriTp De Informatico.Rodri
Tp De Informatico.Rodri
 

Similar a 64-битная версия Loki

Урок 6. Ошибки в 64-битном коде
Урок 6. Ошибки в 64-битном кодеУрок 6. Ошибки в 64-битном коде
Урок 6. Ошибки в 64-битном кодеTatyanazaxarova
 
Алексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кодаАлексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кодаYandex
 
Безопасность 64-битного кода
Безопасность 64-битного кодаБезопасность 64-битного кода
Безопасность 64-битного кодаTatyanazaxarova
 
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...Tatyanazaxarova
 
Краткое описание библиотеки анализа кода VivaCore
Краткое описание библиотеки анализа кода VivaCoreКраткое описание библиотеки анализа кода VivaCore
Краткое описание библиотеки анализа кода VivaCoreTatyanazaxarova
 
64-битный конь, который умеет считать
64-битный конь, который умеет считать64-битный конь, который умеет считать
64-битный конь, который умеет считатьTatyanazaxarova
 
Статический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMergeСтатический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMergeTatyanazaxarova
 
Статический анализ кода для верификации 64-битных приложений
Статический анализ кода для верификации 64-битных приложенийСтатический анализ кода для верификации 64-битных приложений
Статический анализ кода для верификации 64-битных приложенийTatyanazaxarova
 
Intel IPP Samples for Windows - работа над ошибками
Intel IPP Samples for Windows - работа над ошибкамиIntel IPP Samples for Windows - работа над ошибками
Intel IPP Samples for Windows - работа над ошибкамиTatyanazaxarova
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Yauheni Akhotnikau
 
Dynamic Language Runtime
Dynamic Language RuntimeDynamic Language Runtime
Dynamic Language RuntimeSQALab
 
Evgeny Rybak Presentation
Evgeny Rybak PresentationEvgeny Rybak Presentation
Evgeny Rybak Presentationsef2009
 
PVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийPVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийOOO "Program Verification Systems"
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Platonov Sergey
 
Как не подавиться большим старым проектом. Юрий Минаев ➠ CoreHard Autumn 2019
Как не подавиться большим старым проектом. Юрий Минаев ➠  CoreHard Autumn 2019Как не подавиться большим старым проектом. Юрий Минаев ➠  CoreHard Autumn 2019
Как не подавиться большим старым проектом. Юрий Минаев ➠ CoreHard Autumn 2019corehard_by
 
Как не подавиться большим старым проектом
Как не подавиться большим старым проектомКак не подавиться большим старым проектом
Как не подавиться большим старым проектомAndrey Karpov
 
Remote (dev)tools своими руками
Remote (dev)tools своими рукамиRemote (dev)tools своими руками
Remote (dev)tools своими рукамиRoman Dvornov
 
Что такое "Parallel Lint"?
Что такое "Parallel Lint"?Что такое "Parallel Lint"?
Что такое "Parallel Lint"?Tatyanazaxarova
 

Similar a 64-битная версия Loki (20)

Урок 6. Ошибки в 64-битном коде
Урок 6. Ошибки в 64-битном кодеУрок 6. Ошибки в 64-битном коде
Урок 6. Ошибки в 64-битном коде
 
Алексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кодаАлексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кода
 
Безопасность 64-битного кода
Безопасность 64-битного кодаБезопасность 64-битного кода
Безопасность 64-битного кода
 
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...
Использование библиотеки анализа кода OpenC++: модификация, улучшение, исправ...
 
Краткое описание библиотеки анализа кода VivaCore
Краткое описание библиотеки анализа кода VivaCoreКраткое описание библиотеки анализа кода VivaCore
Краткое описание библиотеки анализа кода VivaCore
 
64-битный конь, который умеет считать
64-битный конь, который умеет считать64-битный конь, который умеет считать
64-битный конь, который умеет считать
 
Статический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMergeСтатический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMerge
 
Статический анализ кода для верификации 64-битных приложений
Статический анализ кода для верификации 64-битных приложенийСтатический анализ кода для верификации 64-битных приложений
Статический анализ кода для верификации 64-битных приложений
 
Intel IPP Samples for Windows - работа над ошибками
Intel IPP Samples for Windows - работа над ошибкамиIntel IPP Samples for Windows - работа над ошибками
Intel IPP Samples for Windows - работа над ошибками
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Dynamic Language Runtime
Dynamic Language RuntimeDynamic Language Runtime
Dynamic Language Runtime
 
Evgeny Rybak Presentation
Evgeny Rybak PresentationEvgeny Rybak Presentation
Evgeny Rybak Presentation
 
Breaking logs
Breaking logsBreaking logs
Breaking logs
 
PVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийPVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложений
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
 
Как не подавиться большим старым проектом. Юрий Минаев ➠ CoreHard Autumn 2019
Как не подавиться большим старым проектом. Юрий Минаев ➠  CoreHard Autumn 2019Как не подавиться большим старым проектом. Юрий Минаев ➠  CoreHard Autumn 2019
Как не подавиться большим старым проектом. Юрий Минаев ➠ CoreHard Autumn 2019
 
Как не подавиться большим старым проектом
Как не подавиться большим старым проектомКак не подавиться большим старым проектом
Как не подавиться большим старым проектом
 
Remote (dev)tools своими руками
Remote (dev)tools своими рукамиRemote (dev)tools своими руками
Remote (dev)tools своими руками
 
Net framework
Net frameworkNet framework
Net framework
 
Что такое "Parallel Lint"?
Что такое "Parallel Lint"?Что такое "Parallel Lint"?
Что такое "Parallel Lint"?
 

Más de Tatyanazaxarova

Урок 27. Особенности создания инсталляторов для 64-битного окружения
Урок 27. Особенности создания инсталляторов для 64-битного окруженияУрок 27. Особенности создания инсталляторов для 64-битного окружения
Урок 27. Особенности создания инсталляторов для 64-битного окруженияTatyanazaxarova
 
Урок 26. Оптимизация 64-битных программ
Урок 26. Оптимизация 64-битных программУрок 26. Оптимизация 64-битных программ
Урок 26. Оптимизация 64-битных программTatyanazaxarova
 
Урок 25. Практическое знакомство с паттернами 64-битных ошибок
Урок 25. Практическое знакомство с паттернами 64-битных ошибокУрок 25. Практическое знакомство с паттернами 64-битных ошибок
Урок 25. Практическое знакомство с паттернами 64-битных ошибокTatyanazaxarova
 
Урок 24. Фантомные ошибки
Урок 24. Фантомные ошибкиУрок 24. Фантомные ошибки
Урок 24. Фантомные ошибкиTatyanazaxarova
 
Урок 23. Паттерн 15. Рост размеров структур
Урок 23. Паттерн 15. Рост размеров структурУрок 23. Паттерн 15. Рост размеров структур
Урок 23. Паттерн 15. Рост размеров структурTatyanazaxarova
 
Урок 21. Паттерн 13. Выравнивание данных
Урок 21. Паттерн 13. Выравнивание данныхУрок 21. Паттерн 13. Выравнивание данных
Урок 21. Паттерн 13. Выравнивание данныхTatyanazaxarova
 
Урок 20. Паттерн 12. Исключения
Урок 20. Паттерн 12. ИсключенияУрок 20. Паттерн 12. Исключения
Урок 20. Паттерн 12. ИсключенияTatyanazaxarova
 
Урок 19. Паттерн 11. Сериализация и обмен данными
Урок 19. Паттерн 11. Сериализация и обмен даннымиУрок 19. Паттерн 11. Сериализация и обмен данными
Урок 19. Паттерн 11. Сериализация и обмен даннымиTatyanazaxarova
 
Урок 17. Паттерн 9. Смешанная арифметика
Урок 17. Паттерн 9. Смешанная арифметикаУрок 17. Паттерн 9. Смешанная арифметика
Урок 17. Паттерн 9. Смешанная арифметикаTatyanazaxarova
 
Урок 16. Паттерн 8. Memsize-типы в объединениях
Урок 16. Паттерн 8. Memsize-типы в объединенияхУрок 16. Паттерн 8. Memsize-типы в объединениях
Урок 16. Паттерн 8. Memsize-типы в объединенияхTatyanazaxarova
 
Урок 15. Паттерн 7. Упаковка указателей
Урок 15. Паттерн 7. Упаковка указателейУрок 15. Паттерн 7. Упаковка указателей
Урок 15. Паттерн 7. Упаковка указателейTatyanazaxarova
 
Урок 13. Паттерн 5. Адресная арифметика
Урок 13. Паттерн 5. Адресная арифметикаУрок 13. Паттерн 5. Адресная арифметика
Урок 13. Паттерн 5. Адресная арифметикаTatyanazaxarova
 
Урок 11. Паттерн 3. Операции сдвига
Урок 11. Паттерн 3. Операции сдвигаУрок 11. Паттерн 3. Операции сдвига
Урок 11. Паттерн 3. Операции сдвигаTatyanazaxarova
 
Урок 10. Паттерн 2. Функции с переменным количеством аргументов
Урок 10. Паттерн 2. Функции с переменным количеством аргументовУрок 10. Паттерн 2. Функции с переменным количеством аргументов
Урок 10. Паттерн 2. Функции с переменным количеством аргументовTatyanazaxarova
 
Урок 9. Паттерн 1. Магические числа
Урок 9. Паттерн 1. Магические числаУрок 9. Паттерн 1. Магические числа
Урок 9. Паттерн 1. Магические числаTatyanazaxarova
 
Урок 8. Статический анализ для выявления 64-битных ошибок
Урок 8. Статический анализ для выявления 64-битных ошибокУрок 8. Статический анализ для выявления 64-битных ошибок
Урок 8. Статический анализ для выявления 64-битных ошибокTatyanazaxarova
 
Урок 7. Проблемы выявления 64-битных ошибок
Урок 7. Проблемы выявления 64-битных ошибокУрок 7. Проблемы выявления 64-битных ошибок
Урок 7. Проблемы выявления 64-битных ошибокTatyanazaxarova
 
Урок 5. Сборка 64-битного приложения
Урок 5. Сборка 64-битного приложенияУрок 5. Сборка 64-битного приложения
Урок 5. Сборка 64-битного приложенияTatyanazaxarova
 
Урок 4. Создание 64-битной конфигурации
Урок 4. Создание 64-битной конфигурацииУрок 4. Создание 64-битной конфигурации
Урок 4. Создание 64-битной конфигурацииTatyanazaxarova
 
PVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийPVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийTatyanazaxarova
 

Más de Tatyanazaxarova (20)

Урок 27. Особенности создания инсталляторов для 64-битного окружения
Урок 27. Особенности создания инсталляторов для 64-битного окруженияУрок 27. Особенности создания инсталляторов для 64-битного окружения
Урок 27. Особенности создания инсталляторов для 64-битного окружения
 
Урок 26. Оптимизация 64-битных программ
Урок 26. Оптимизация 64-битных программУрок 26. Оптимизация 64-битных программ
Урок 26. Оптимизация 64-битных программ
 
Урок 25. Практическое знакомство с паттернами 64-битных ошибок
Урок 25. Практическое знакомство с паттернами 64-битных ошибокУрок 25. Практическое знакомство с паттернами 64-битных ошибок
Урок 25. Практическое знакомство с паттернами 64-битных ошибок
 
Урок 24. Фантомные ошибки
Урок 24. Фантомные ошибкиУрок 24. Фантомные ошибки
Урок 24. Фантомные ошибки
 
Урок 23. Паттерн 15. Рост размеров структур
Урок 23. Паттерн 15. Рост размеров структурУрок 23. Паттерн 15. Рост размеров структур
Урок 23. Паттерн 15. Рост размеров структур
 
Урок 21. Паттерн 13. Выравнивание данных
Урок 21. Паттерн 13. Выравнивание данныхУрок 21. Паттерн 13. Выравнивание данных
Урок 21. Паттерн 13. Выравнивание данных
 
Урок 20. Паттерн 12. Исключения
Урок 20. Паттерн 12. ИсключенияУрок 20. Паттерн 12. Исключения
Урок 20. Паттерн 12. Исключения
 
Урок 19. Паттерн 11. Сериализация и обмен данными
Урок 19. Паттерн 11. Сериализация и обмен даннымиУрок 19. Паттерн 11. Сериализация и обмен данными
Урок 19. Паттерн 11. Сериализация и обмен данными
 
Урок 17. Паттерн 9. Смешанная арифметика
Урок 17. Паттерн 9. Смешанная арифметикаУрок 17. Паттерн 9. Смешанная арифметика
Урок 17. Паттерн 9. Смешанная арифметика
 
Урок 16. Паттерн 8. Memsize-типы в объединениях
Урок 16. Паттерн 8. Memsize-типы в объединенияхУрок 16. Паттерн 8. Memsize-типы в объединениях
Урок 16. Паттерн 8. Memsize-типы в объединениях
 
Урок 15. Паттерн 7. Упаковка указателей
Урок 15. Паттерн 7. Упаковка указателейУрок 15. Паттерн 7. Упаковка указателей
Урок 15. Паттерн 7. Упаковка указателей
 
Урок 13. Паттерн 5. Адресная арифметика
Урок 13. Паттерн 5. Адресная арифметикаУрок 13. Паттерн 5. Адресная арифметика
Урок 13. Паттерн 5. Адресная арифметика
 
Урок 11. Паттерн 3. Операции сдвига
Урок 11. Паттерн 3. Операции сдвигаУрок 11. Паттерн 3. Операции сдвига
Урок 11. Паттерн 3. Операции сдвига
 
Урок 10. Паттерн 2. Функции с переменным количеством аргументов
Урок 10. Паттерн 2. Функции с переменным количеством аргументовУрок 10. Паттерн 2. Функции с переменным количеством аргументов
Урок 10. Паттерн 2. Функции с переменным количеством аргументов
 
Урок 9. Паттерн 1. Магические числа
Урок 9. Паттерн 1. Магические числаУрок 9. Паттерн 1. Магические числа
Урок 9. Паттерн 1. Магические числа
 
Урок 8. Статический анализ для выявления 64-битных ошибок
Урок 8. Статический анализ для выявления 64-битных ошибокУрок 8. Статический анализ для выявления 64-битных ошибок
Урок 8. Статический анализ для выявления 64-битных ошибок
 
Урок 7. Проблемы выявления 64-битных ошибок
Урок 7. Проблемы выявления 64-битных ошибокУрок 7. Проблемы выявления 64-битных ошибок
Урок 7. Проблемы выявления 64-битных ошибок
 
Урок 5. Сборка 64-битного приложения
Урок 5. Сборка 64-битного приложенияУрок 5. Сборка 64-битного приложения
Урок 5. Сборка 64-битного приложения
 
Урок 4. Создание 64-битной конфигурации
Урок 4. Создание 64-битной конфигурацииУрок 4. Создание 64-битной конфигурации
Урок 4. Создание 64-битной конфигурации
 
PVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложенийPVS-Studio, решение для разработки современных ресурсоемких приложений
PVS-Studio, решение для разработки современных ресурсоемких приложений
 

64-битная версия Loki

  • 1. 64-битная версия Loki Авторы: Евгений Рыжков, Андрей Карпов, Андрей Александреску, Питер Кюмель, Рич Спозато, Дата: 25.09.2009 Аннотация Статья представляет собой отчет о проверки библиотеки Loki на совместимость с 64-битными системами с помощью анализатора кода Viva64 компании ООО "СиПроВер". Содержатся рекомендации пользователям библиотеки. Статья будет полезна также пользователям других библиотек, построенных на шаблонах, так как раскрывает особенности анализа подобных библиотек. Введение Библиотека Loki разработана Андреем Александреску как часть книги "Современное проектирование на С++: Обобщенное программирование и прикладные шаблоны проектирования". Аннотация к книге гласит: "В книге изложена новая технология программирования, представляющая собой сплав обобщенного программирования, метапрограммирования шаблонов и объектно-ориентированного программирования на C++. Настраиваемые компоненты, созданные автором, высоко подняли уровень абстракции, наделив язык C++ чертами языка спецификации проектирования, сохранив всю его мощь и выразительность". Компания ООО "СиПроВер", создающая анализатор кода Viva64 для разработки 64-битных приложений, активно общается с авторами различных программных проектов. Однажды к нам обратился Рич Спозато (Rich Sposato), один из администраторов проекта Loki, и попросил проверить код библиотеки на предмет совместимости с 64-битными системами с помощью нашего инструмента Viva64. Мы сразу же согласились. Ведь это не только возможность принести пользу сообществу разработчиков, но и настоящий "тест выносливости" для нашего анализатора кода Viva64. Всем известно, что библиотека Loki написана с применением самых современных и мощных возможностей языка Си++. И если анализатор Viva64 справится с Loki, то и другие более простые проекты не вызовут никаких проблем. Надо заметить, что данная статья основана на версии Loki от мая 2009 года (новее, чем официальная на тот момент версия Loki 0.1.7), поэтому в более новых версиях Loki указанные проблемы будут устранены. Итак, мы скачали последнюю версию Loki из SVN-репозитория и приступили к работе. Сборка 64-битной Loki в Microsoft Visual Studio 2005 Анализатор кода Viva64 интегрируется в среду разработки Microsoft Visual Studio, поэтому разумно было собрать версию Loki именно для этой среды. В составе пакета Loki есть готовые файлы решений для Visual Studio 2005 и Visual Studio 2008. Однако на момент мая 2009 года эти решения содержат лишь 32-битные конфигурации. Поэтому необходимо в Visual Studio создать
  • 2. конфигурации для платформы x64. Добавив нужные конфигурации можно запустить компиляцию 64-битной версии. Библиотека Loki предназначена для работы на большом количестве различных платформ и собирается с помощью многих наиболее известных компиляторов. Именно поэтому 64-битная версия Loki скомпилировалась практически сразу же. Из 20 проектов, входящих в решение, не собрался только один: ========== Build: 19 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== Это был проект SafeFormat: 16>------ Build started: Project: SafeFormat, Configuration: Debug x64 ------ 16>Compiling... 16>main.cpp 16>.main.cpp(255) : error C3066: there are multiple ways that an object of this type can be called with these arguments 16> ....includeloki/SafeFormat.h(109): could be 'Loki::PrintfState<Device,Char> &Loki::PrintfState<Device,Char>::operator ()(bool)' ... 16> while trying to match the argument list '(UInt)' Текст ошибки несколько сокращен, поскольку полностью он займет целую страницу. Посмотрим на код, который приводит к ошибке: void test_dword() { typedef signed int Int; typedef unsigned int UInt; typedef signed long Long; typedef unsigned long ULong; Int i(0); UInt ui(0); Long l(0); ULong ul(0); Printf("%d")(i);
  • 3. Printf("%d")(ui); // Проблема в этой строке Printf("%d")(l); Printf("%d")(ul); } Printf - это функция, внутри которой используется макрос LOKI_PRINTF_STATE_FORWARD. С помощью этого макроса задается ряд вспомогательных функций. В нем-то и кроется проблема. Внутри файла SafeFormat.h вместо следующего фрагмента: #if (defined(_WIN32) || defined(_WIN64)) LOKI_PRINTF_STATE_FORWARD(unsigned long) #else необходимо написать так: #if (defined(_WIN32) || defined(_WIN64)) #if (defined(_WIN64)) LOKI_PRINTF_STATE_FORWARD(unsigned int) #endif LOKI_PRINTF_STATE_FORWARD(unsigned long) #else После этого исправления ошибка компиляции пропадет и все 20 проектов библиотеки скомпилируются. Однако среди прочих диагностических сообщений (warnings) компилятора мы видим сообщение, касающееся 64-битного кода: 2>.CachedFactoryTest.cpp(204) : warning C4267: 'argument' : conversion from 'size_t' to 'const int', possible loss of data 2> .CachedFactoryTest.cpp(238) : see reference to function template instantiation 'milliSec typicalUse<Cache> (Cache &,unsigned int,unsigned int,unsigned int)' being compiled 2> with 2> [ 2> Cache=CRandomEvict 2> ]
  • 4. 2> .CachedFactoryTest.cpp(252) : see reference to function template instantiation 'void displayTypicalUse<CRandomEvict> (Cache &,unsigned int,unsigned int,unsigned int)' being compiled 2> with 2> [ 2> Cache=CRandomEvict 2> ] Это сообщение говорит о потенциально опасном преобразовании типа size_t внутри функции typicalUse() в файле CachedFactoryTest.cpp: // Registering objects for(size_t i=0;i<objectKind;i++) CC.Register(i, createProductNull); Граница цикла (переменная objectKind) представлена типом unsigned. Поэтому использовать для счетчика цикла переменную типа size_t не имеет смысла. После исправления типа счетчика цикла проблема исчезнет: // Registering objects for(unsigned i=0;i<objectKind;i++) CC.Register(i, createProductNull); После этих небольших исправлений мы имеем 64-битную библиотеку, которая успешно компилируется и не выдает никаких диагностических сообщений (warnings) насчет 64-битности. Но насколько в действительности код библиотеки корректен? Это мы определим с помощью нашего анализатора кода Viva64. Проверка 64-битной Loki с помощью Viva64 Для того чтобы убедится в совместимости Loki с 64-битными системами, выполним анализ кода с помощью Viva64. Анализатор кода Viva64 предназначен для разработки новых 64-битных приложений и для миграций существующих 32-битных на 64-битную платформу. Запуск Viva64 для анализа Loki выявил список из 89 потенциально-опасных синтаксических конструкций. Это не значит, что в библиотеке Loki содержится 89 ошибок, связанных с 64-битным кодом. Но все эти 89 мест должен просмотреть разработчик для того, чтобы понять, действительно ли там возможна ошибка или нет. Разумеется, мы проанализировали эти ошибки. 1 Некорректно используемая константа LONG_MIN Начнем с ошибки, связанной с некорректно используемой константой LONG_MIN в следующей функции:
  • 5. char* RenderWithoutSign(LOKI_SAFEFORMAT_SIGNED_LONG n, char* bufLast, unsigned int base, bool uppercase) Она находится в файле SafeFormat.h. Проблема в строке: if (n != LONG_MIN) { Тип LOKI_SAFEFORMAT_SIGNED_LONG объявляется как тип, способный вмещать 64-битные значения в 64-битной системе. В Unix-системах (с моделью данных LP64) для этого используют тип long. Но в 64-битных Windows-системах (модель данных LLP64) тип long остался 32-битным. Поэтому в Loki тип LOKI_SAFEFORMAT_SIGNED_LONG объявлен так: #if defined(_WIN32) || defined(_WIN64) #define LOKI_SAFEFORMAT_SIGNED_LONG intptr_t #define LOKI_SAFEFORMAT_UNSIGNED_LONG uintptr_t #else #define LOKI_SAFEFORMAT_SIGNED_LONG signed long #define LOKI_SAFEFORMAT_UNSIGNED_LONG unsigned long #endif Поскольку тип long в 64-битных Windows-системах остался 32-битным, то и константа LONG_MIN задает минимальное значение 32-битной переменной. А это значит, что ее использование некорректно при работе с 64-битными типами (в нашем случае с intptr_t). Решением будет использование собственной константы. Например, исправление может выглядеть так: #if defined(_WIN32) || defined(_WIN64) # define LOKI_SAFEFORMAT_SIGNED_LONG intptr_t #if defined(_WIN64) # define LOKI_SAFEFORMAT_SIGNED_LONG_MIN_VALUE LLONG_MIN # define LOKI_SAFEFORMAT_SIGNED_LONG_MAX_VALUE LLONG_MAX #else # define LOKI_SAFEFORMAT_SIGNED_LONG_MIN_VALUE LONG_MIN # define LOKI_SAFEFORMAT_SIGNED_LONG_MAX_VALUE LONG_MAX #endif ... #else # define LOKI_SAFEFORMAT_SIGNED_LONG signed long # define LOKI_SAFEFORMAT_SIGNED_LONG_MIN_VALUE LONG_MIN
  • 6. # define LOKI_SAFEFORMAT_SIGNED_LONG_MAX_VALUE LONG_MAX ... #endif И, соответственно, строку if (n != LONG_MIN) { надо заменить на строку if (n != LOKI_SAFEFORMAT_SIGNED_LONG_MIN_VALUE) { К счастью и к похвале создателей библиотеки Loki это единственное место, которое заслуживавет исправления. Описанные далее замечания могут быть интересны, но не имеют важности. 2 Некоторые виды магических чисел - ошибка или нет? Одной из проблем, выявляемой анализатором Viva64 являются магические числа. С точки зрения миграции кода с 32-битной на 64-битную платформу есть ряд чисел, использование которых наиболее опасно. Возможно, где-то в коде программист рассчитывает на определенный размер типа данных, что может вызвать проблему. Те, кто смотрят на сообщения от анализаторов кода, часто жалуются на бессмысленность подобных сообщений. Действительно, какой смысл ругаться анализатору кода на число 4 в подобных строках: ::Loki::ScopeGuard guard4 = ::Loki::MakeGuard( &HasFour, 1, 2, 3, 4 ); ::Loki::ScopeGuard guard5 = ::Loki::MakeGuard( &HasFive, 1, 2, 3, 4, 5 ); Но бывают такие конструкции, которые надо анализировать очень тщательно. Например, в файле SafeFormatmain.cpp видим код: case 'X': // TestCase(formatSpec, RandomInt(-10000, 10000)); // don't test negative values on 64bit systems, because // snprintf does not support 64 Bit values TestCase(formatSpec, RandomInt( -10000 * (sizeof(size_t)>4 ? 0 : 1) , 10000)); break; case 'e': Конкретно в этом месте проблемы, конечно же, нет. Но диагностика магических чисел в анализаторе кода нужна именно для нахождения таких конструкций в коде. 3 Прибавление int к указателю - потенциальная проблема Файл flexsimplestringstorage.h содержит функцию: void resize(size_type newSize, E fill)
  • 7. { const int delta = int(newSize - size()); if (delta == 0) return; if (delta > 0) { if (newSize > capacity()) { reserve(newSize); } E* e = &*end(); flex_string_details::pod_fill(e, e + delta, fill); } pData_->pEnd_ = pData_->buffer_ + newSize; } Анализатор Viva64 сообщает о потенциальной проблеме здесь: flex_string_details::pod_fill(e, e + delta, fill); Недостаток кода заключается в том, что к указателю e прибавляется переменная delta типа int. Это потенциальная проблема, так как функция pod_fill не сможет обрабатывать объем данных более двух гигабайт (INT_MAX символов). Конечно же, конкретно здесь ошибки, видимо, нет, поскольку вряд ли бывают строки более двух гигабайт. Но лучше все-таки заменить тип переменной delta с int на ptrdiff_t: const ptrdiff_t delta = ptrdiff_t(newSize - size()); 4 Использование int для индексации массивов некорректно Для доступа к большим массивам данным (более INT_MAX элементов) надо использовать типы ptrdiff_t или size_t. В файле SmallObjSmallObjBench.cpp присутсвует довольно большой макрос LOKI_SMALLOBJ_BENCH_ARRAY, в котором работа с массивом ведется через индексацию по int. Хотя это лучше исправить, в данном месте это не является ошибкой. 5 Правильные аргументы функций Внутри файла CachedFactoryCachedFactoryTest.cpp объявлена функция: template< class Cache > milliSec typicalUse(Cache &CC, unsigned objectKind, unsigned maxObjectCount, unsigned maxIteration)
  • 8. Для параметра objectKind лучше использовать тип size_t. Но поскольку этот код относится к тестам, то какой-либо серьезного недостатка в этом нет. Библиотека Loki совместима с 64-битными системами - значит программа, использующая ее также совместима? Все немногие обнаруженные проблемы библиотеки Loki, перечисленные ранее, легко исправимы. Значит ли это, что если в Loki нет никаких 64-битных проблем (а это именно так), то и приложение, использующее эту библиотеку, безопасно с точки зрения 64-битного кода? К сожалению нет! Все дело в том, что библиотека Loki крайне активно использует шаблоны. А когда анализатор кода разбирает код шаблона, он не всегда может диагностировать проблему. Для полной уверенности анализатору необходимо выполнить инстанцирование шаблонных классов и функций. Приведем просто пример, не относящийся к библиотеке Loki. Анализатор Viva64 среди прочих проблем в коде может обнаруживать неоптимальные структуры данных: template <class T> struct TClass { int m_a; T m_b; int m_c; }; Если здесь T имеет тип int, то структура оптимальна. Если же T имеет тип size_t, то структура займет 24 байта, вместо возможных 16 байтах. Тогда в случае большого количества подобных объектов лучше было бы переписать: template <class T> struct TClass { T m_b; int m_a; int m_c; }; Но проверить это анализатор может только выполнив инстанцирование шаблона. То есть имея лишь объявление класса в заголовке выявит проблему нельзя. Другой пример, опять же не относящийся к Loki, связанный с приведением типов: template<typename T1, typename T2>
  • 9. class TemplateClass { public: void test1() { m_a.m_value = m_b.m_value; // Есть ли здесь ошибка? } private: T1 m_a; T2 m_b; }; В данном коде ошибка приведения типов может быть, а может и не быть, в зависимости от того, с какими параметрами будет выполнено инстанцирование шаблона TemplateClass. Только анализируя код функции, не выполняя инстанцирование, анализатор не может сообщить об ошибке. Перечисленные два примера шаблонных классов не относятся к библиотеке Loki, однако важны для понимания принципов работы анализаторов кода. Особенность шаблонных библиотек типа Loki заключается в том, что даже если библиотека полностью совместима с 64-битными системами, это не значит что код, который ее использует, корректен. Это в корне меняет подход к верификации приложений. Если при работе с обычной (не шаблонной) библиотекой достаточно быть уверенным, что библиотека корректна с точки зрения 64-бит для того, чтобы быть уверенным в корректности всего приложения, то с шаблонными библиотеками такой уверенности уже быть не может. Все это означает, что хотя библиотека Loki и не содержит проблем 64-битного кода, пользовательское приложение, которое ее использует должно быть дополнительно проверено анализатором кода на отсутствие подобных проблем. Ведь ошибки зависят от того, с какими параметрами выполняется инстанцирование шаблонов. Выводы По результатам работы сотрудников компании ООО "СиПроВер" над проверкой на совместимость с 64-бибтными системами библиотеки Loki сделаны следующие выводы: Библиотека полностью совместима с 64-битными системами и не содержит потенциальных ошибок. Указанные в данной статье ошибки, скорее всего, будут очень быстро исправлены. Анализатор кода Viva64, предназначенный для разработки новых 64-битных и миграции старых 32-битных приложений показал себя очень хорошо при проверке сложного шаблонного кода библиотеки. Это говорит о высоком качестве анализатора кода.
  • 10. Хотя библиотека Loki и не содержит 64-битных проблем, они возможны в пользовательских приложениях, использующих Loki. Поскольку конечный код зависит от того, с какими параметрами инстанцировались шаблоны, то обязательно надо проверять пользовательские приложения анализатором кода. Только тогда можно быть уверенным в полной совместимости приложения с 64-битными системами. Благодарность Благодарим всех, кто принимал участие в анализе библиотеки Loki и в оценке этой работы в команде Loki: • Спасибо компании ООО "СиПроВер", которая проанализировала код библиотеки Loki и выполнила верификацию ее для работы в 64-битном режиме, в частности: Андрею Карпову и Евгению Рыжкову. • Спасибо команде Loki: Андрею Александреску, Питеру Кюмелю, Ричу Спозато за совместную работу над проверкой и редактированием статьи, а также ценные замечания. • Спасибо Ричу Спозато, за координирование всей работы. Библиографический список 1. Библиотека Loki. http://www.viva64.com/go.php?url=515. 2. Анализатор кода Viva64. http://www.viva64.com/viva64-tool.