конкатенация строк, соответствие log4cplus и MISRA

#c #misra #log4cplus

#c #misra #log4cplus

Вопрос:

Я использую log4cplus , и мой misra-проверяет наличие чего-то столь же невинного, как

 LOG4CPLUS_INFO(
        logger,
        std::string("ABC")   std::string("DEF"));
 

выход (среди прочего) The underlying type of `0L` is implicitly reduced from `8-bit signed char` to {code{bool}}. . Это происходит также, когда я помещаю соответствующие литералы, а не помещаю их внутрь string . Интересно, как это исправить. Или, в более общем смысле, как бы вы объединили несколько сообщений журнала и при этом сохранили MISRA-проверки счастливыми?

Комментарии:

1. MISRA позволяет использовать объединение двух строк. Я не знаком с log4cplus, но это может быть вызов макроса, который не нравится MISRA. В качестве альтернативы, если он не жалуется на одно сообщение, просто создайте строку заранее и передайте объединенную строку.

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

3. @user7860670 Динамическая память также не должна использоваться и std::string использует это, есть много вещей, которые она не допускает

4. Действительно… почему вы используете std::string в приложении MISRA? Не говоря уже об этом зловещем функциональном макросе.

Ответ №1:

Я взглянул на LOG4CPLUS_INFO и это макрос, определенный как:

 #if !defined(LOG4CPLUS_DISABLE_INFO)
#define LOG4CPLUS_INFO(logger, logEvent)                                
    LOG4CPLUS_MACRO_BODY (logger, logEvent, INFO_LOG_LEVEL)
 

и LOG4CPLUS_MACRO_BODY определяется как:

  #define LOG4CPLUS_MACRO_BODY(logger, logEvent, logLevel)                
     LOG4CPLUS_SUPPRESS_DOWHILE_WARNING()                                
     do {                                                                
         log4cplus::Logger const amp; _l                                    
             = log4cplus::detail::macros_get_logger (logger);            
         if (LOG4CPLUS_MACRO_LOGLEVEL_PRED (                             
                 _l.isEnabledFor (log4cplus::logLevel), logLevel)) {     
             LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM (_log4cplus_buf); 
             _log4cplus_buf << logEvent;                                 
             log4cplus::detail::macro_forced_log (_l,                    
                 log4cplus::logLevel, _log4cplus_buf.str(),              
                 __FILE__, __LINE__, LOG4CPLUS_MACRO_FUNCTION ());       
         }                                                               
     } while (0)                                                         
     LOG4CPLUS_RESTORE_DOWHILE_WARNING()
 

и поэтому ваш MISRA checker будет проверять вызов макроса. И МИСРА любит if , чтобы утверждения были определены явно в терминах bool , например, а не if(node) как ему нравится if(node!=nullptr) , и я думаю, что у него может быть проблема с последней строкой:

      } while (0)                                                         
 

As 0 неявно преобразуется в bool . Вы должны посмотреть, получите ли вы такое же предупреждение, добавив простой do{}while(0); цикл в свой код и снова запустив средство проверки.


И если вам нужен безопасный способ ведения журнала MISRA, я бы избегал использования макросов. Вы можете создать простой класс ведения журнала с помощью a std::ofstream и a std::mutex и сохранить его в области пространства имен, определенной как extern в вашем заголовочном файле.

Комментарии:

1. Правда, я также обнаружил это, изучив исходный код библиотеки log4cplus…

2. Позвольте мне добавить, что макросы log4cplus предназначены только для удобства. Вы можете реализовать любые средства ведения журнала, которые вы хотите, с помощью методов API без каких-либо макросов.