Поддержка C++ на avr в gcc

  • strict warning: Non-static method GalleryDataCache::put() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/embed.php on line 32.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 85.
  • strict warning: Non-static method GalleryEmbed::getEmbedPathByHttpRequest() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/embed.php on line 36.
  • strict warning: Non-static method GalleryUtilities::getRequestVariablesNoPrefix() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 1092.
  • strict warning: Non-static method GalleryUtilities::_getRequestVariable() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUtilities.class on line 289.
  • strict warning: Non-static method GalleryUtilities::_internalGetRequestVariable() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUtilities.class on line 875.
  • strict warning: Non-static method GalleryUtilities::_internalGetRequestVariable() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUtilities.class on line 879.
  • strict warning: Non-static method GalleryUtilities::sanitizeInputValues() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUtilities.class on line 293.
  • strict warning: Non-static method GalleryUtilities::sanitizeInputValues() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUtilities.class on line 708.
  • strict warning: Non-static method GalleryUtilities::sanitizeInputValues() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUtilities.class on line 714.
  • strict warning: Non-static method GalleryEmbed::init() should not be called statically in /var/www/kibergus.su/htdocs/sites/all/modules/gallery/gallery_base.inc on line 134.
  • strict warning: Non-static method GalleryDataCache::containsKey() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 94.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 203.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 46.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 47.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 48.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 49.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryModule.class on line 21.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 55.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryPlatform/UnixPlatform.class on line 21.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 107.
  • strict warning: Non-static method GalleryUtilities::getRequestVariables() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 150.
  • strict warning: Non-static method GalleryUtilities::_getRequestVariable() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUtilities.class on line 242.
  • strict warning: Non-static method GalleryUtilities::_internalGetRequestVariable() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUtilities.class on line 875.
  • strict warning: Non-static method GalleryUtilities::_internalGetRequestVariable() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUtilities.class on line 879.
  • strict warning: Non-static method GalleryUtilities::sanitizeInputValues() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUtilities.class on line 246.
  • strict warning: Non-static method GalleryUtilities::sanitizeInputValues() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUtilities.class on line 708.
  • strict warning: Non-static method GalleryUtilities::sanitizeInputValues() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUtilities.class on line 714.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 152.
  • strict warning: Non-static method GalleryTranslator::getSupportedLanguageCode() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 154.
  • strict warning: Non-static method GalleryTranslator::getLanguageData() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryTranslator.class on line 414.
  • strict warning: Non-static method GalleryUtilities::strToUpper() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryTranslator.class on line 418.
  • strict warning: Non-static method GalleryDataCache::put() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 103.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 85.
  • strict warning: Non-static method GalleryEmbed::isCompatibleWithEmbedApi() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 107.
  • strict warning: Non-static method GalleryEmbed::getApiVersion() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 61.
  • strict warning: Non-static method GalleryUtilities::isCompatibleWithApi() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 61.
  • strict warning: Non-static method GalleryDataCache::containsKey() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 128.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 203.
  • strict warning: Non-static method GalleryCoreApi::getAllFactoryImplementationIds() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 179.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 187.
  • strict warning: Non-static method GalleryFactoryHelper_simple::getAllImplementationIds() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 188.
  • strict warning: Non-static method GalleryFactoryHelper_simple::_getFactoryData() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryFactoryHelper_simple.class on line 213.
  • strict warning: Non-static method GalleryFactoryHelper_simple::_getSingleton() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryFactoryHelper_simple.class on line 63.
  • strict warning: Non-static method GalleryCoreApi::newFactoryInstanceById() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 186.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 174.
  • strict warning: Non-static method GalleryFactoryHelper_simple::newInstanceById() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 175.
  • strict warning: Non-static method GalleryFactoryHelper_simple::_getFactoryData() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryFactoryHelper_simple.class on line 191.
  • strict warning: Non-static method GalleryFactoryHelper_simple::_getSingleton() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryFactoryHelper_simple.class on line 63.
  • strict warning: Non-static method GalleryFactoryHelper_simple::newInstance() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryFactoryHelper_simple.class on line 201.
  • strict warning: Non-static method GalleryFactoryHelper_simple::_getFactoryData() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryFactoryHelper_simple.class on line 141.
  • strict warning: Non-static method GalleryFactoryHelper_simple::_getSingleton() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryFactoryHelper_simple.class on line 63.
  • strict warning: Non-static method GalleryCoreApi::getAnonymousUserId() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 203.
  • strict warning: Non-static method GalleryCoreApi::getPluginParameter() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 3078.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 300.
  • strict warning: Non-static method GalleryPluginHelper_simple::getParameter() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 302.
  • strict warning: Non-static method GalleryPluginHelper_simple::_fetchAllParameters() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 222.
  • strict warning: Non-static method GalleryDataCache::containsKey() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 281.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 203.
  • strict warning: Non-static method GalleryDataCache::get() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 282.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 186.
  • strict warning: Non-static method GalleryCoreApi::loadEntitiesById() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/init.inc on line 208.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 2360.
  • strict warning: Non-static method GalleryEntityHelper_simple::loadEntitiesById() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 2361.
  • strict warning: Non-static method GalleryDataCache::containsKey() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryEntityHelper_simple.class on line 53.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 203.
  • strict warning: Non-static method GalleryDataCache::getFromDisk() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryEntityHelper_simple.class on line 56.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 273.
  • strict warning: Non-static method GalleryDataCache::getCachePath() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 280.
  • strict warning: Non-static method GalleryDataCache::getCacheTuple() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 405.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 287.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUser.class on line 21.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEntity.class on line 21.
  • strict warning: Declaration of GalleryUser::create() should be compatible with GalleryEntity::create() in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUser.class on line 42.
  • strict warning: Declaration of GalleryUser::save() should be compatible with GalleryEntity::save($postEvent = true, $setAclId = NULL) in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryUser.class on line 42.
  • strict warning: Non-static method GalleryDataCache::put() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryEntityHelper_simple.class on line 95.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 85.
  • strict warning: Non-static method GalleryUtilities::isA() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryEntityHelper_simple.class on line 118.
  • strict warning: Non-static method GalleryDataCache::put() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 133.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 85.
  • strict warning: Non-static method GalleryEmbed::done() should not be called statically in /var/www/kibergus.su/htdocs/sites/all/modules/gallery/gallery_block.inc on line 36.
  • strict warning: Non-static method GalleryEmbed::getBlock() should not be called statically in /var/www/kibergus.su/htdocs/sites/all/modules/gallery/gallery_block.inc on line 194.
  • strict warning: Non-static method GalleryCoreApi::fetchPluginStatus() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 994.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 368.
  • strict warning: Non-static method GalleryPluginHelper_simple::fetchPluginStatus() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 369.
  • strict warning: Non-static method GalleryDataCache::containsKey() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 347.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 203.
  • strict warning: Non-static method GalleryDataCache::getFromDisk() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 352.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 273.
  • strict warning: Non-static method GalleryDataCache::getCachePath() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 280.
  • strict warning: Non-static method GalleryDataCache::getCacheTuple() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 438.
  • strict warning: Non-static method GalleryDataCache::put() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 444.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 85.
  • strict warning: Non-static method GalleryCoreApi::getCodeBasePath() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 1000.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 1006.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 1012.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryTheme.class on line 21.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 1020.
  • strict warning: Non-static method GalleryView::setStandardTemplateVariables() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEmbed.class on line 1021.
  • strict warning: Non-static method GalleryCoreApi::isAnonymousUser() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryView.class on line 660.
  • strict warning: Non-static method GalleryCoreApi::getAnonymousUserId() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 3098.
  • strict warning: Non-static method GalleryCoreApi::getPluginParameter() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 3078.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 300.
  • strict warning: Non-static method GalleryPluginHelper_simple::getParameter() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 302.
  • strict warning: Non-static method GalleryPluginHelper_simple::_fetchAllParameters() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 222.
  • strict warning: Non-static method GalleryDataCache::containsKey() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 281.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 203.
  • strict warning: Non-static method GalleryDataCache::get() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 282.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 186.
  • strict warning: Non-static method GalleryCoreApi::isUserInSiteAdminGroup() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryView.class on line 665.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 1775.
  • strict warning: Non-static method GalleryUserGroupHelper_simple::isUserInSiteAdminGroup() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 1776.
  • strict warning: Non-static method GalleryCoreApi::getPluginParameter() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryUserGroupHelper_simple.class on line 41.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 300.
  • strict warning: Non-static method GalleryPluginHelper_simple::getParameter() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 302.
  • strict warning: Non-static method GalleryPluginHelper_simple::_fetchAllParameters() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 222.
  • strict warning: Non-static method GalleryDataCache::containsKey() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 281.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 203.
  • strict warning: Non-static method GalleryDataCache::get() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 282.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 186.
  • strict warning: Non-static method GalleryUserGroupHelper_simple::isUserInGroup() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryUserGroupHelper_simple.class on line 46.
  • strict warning: Non-static method GalleryDataCache::containsKey() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryUserGroupHelper_simple.class on line 62.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 203.
  • strict warning: Non-static method GalleryCoreApi::getMapEntry() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryUserGroupHelper_simple.class on line 68.
  • strict warning: Non-static method GalleryDataCache::put() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryUserGroupHelper_simple.class on line 74.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 85.
  • strict warning: Declaration of GalleryChildEntity::create() should be compatible with GalleryEntity::create() in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryChildEntity.class on line 0.
  • strict warning: Declaration of GalleryChildEntity::createLink() should be compatible with GalleryEntity::createLink($entity) in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryChildEntity.class on line 0.
  • strict warning: Declaration of GalleryFileSystemEntity::create() should be compatible with GalleryChildEntity::create($parentId) in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryFileSystemEntity.class on line 44.
  • strict warning: Declaration of GalleryItem::save() should be compatible with GalleryEntity::save($postEvent = true, $setAclId = NULL) in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryItem.class on line 44.
  • strict warning: Declaration of GalleryAlbumItem::create() should be compatible with GalleryItem::create($parentId, $path, $canContainChildren = false) in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryAlbumItem.class on line 41.
  • strict warning: Only variables should be passed by reference in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEvent.class on line 54.
  • strict warning: Declaration of mapModule::getItemLinks() should be compatible with GalleryModule::getItemLinks($items, $wantsDetailedLinks, $permissions, $userId) in /var/www/kibergus.su/htdocs/gallery2/modules/map/module.inc on line 0.
  • strict warning: Declaration of mapModule::getItemSummaries() should be compatible with GalleryModule::getItemSummaries($items, $permissions, &$template) in /var/www/kibergus.su/htdocs/gallery2/modules/map/module.inc on line 0.
  • strict warning: Declaration of GalleryDataItem::create() should be compatible with GalleryItem::create($parentId, $path, $canContainChildren = false) in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataItem.class on line 417.
  • strict warning: Declaration of GalleryDerivativeImage::create() should be compatible with GalleryDerivative::create($parentId) in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDerivativeImage.class on line 40.
  • strict warning: Non-static method GalleryDataCache::containsKey() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/lib/smarty_plugins/modifier.markup.php on line 46.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 203.
  • strict warning: Non-static method GalleryCoreApi::getPluginParameter() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/lib/smarty_plugins/modifier.markup.php on line 48.
  • strict warning: Non-static method GalleryCoreApi::requireOnce() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 300.
  • strict warning: Non-static method GalleryPluginHelper_simple::getParameter() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryCoreApi.class on line 302.
  • strict warning: Non-static method GalleryPluginHelper_simple::_fetchAllParameters() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 222.
  • strict warning: Non-static method GalleryDataCache::containsKey() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 281.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 203.
  • strict warning: Non-static method GalleryDataCache::get() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/helpers/GalleryPluginHelper_simple.class on line 282.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 186.
  • strict warning: Non-static method GalleryDataCache::put() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/lib/smarty_plugins/modifier.markup.php on line 53.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 85.
  • strict warning: Non-static method GalleryDataCache::get() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/lib/smarty_plugins/modifier.markup.php on line 56.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 186.
  • strict warning: Non-static method GalleryDataCache::containsKey() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/lib/smarty_plugins/modifier.markup.php on line 46.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 203.
  • strict warning: Non-static method GalleryDataCache::get() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/lib/smarty_plugins/modifier.markup.php on line 56.
  • strict warning: Non-static method GalleryDataCache::_getCache() should not be called statically in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryDataCache.class on line 186.
  • strict warning: Only variables should be passed by reference in /var/www/kibergus.su/htdocs/gallery2/modules/core/classes/GalleryEvent.class on line 54.
  • strict warning: Non-static method GalleryEmbed::parseHead() should not be called statically in /var/www/kibergus.su/htdocs/sites/all/modules/gallery/gallery_base.inc on line 495.
  • strict warning: Non-static method GalleryEmbed::done() should not be called statically in /var/www/kibergus.su/htdocs/sites/all/modules/gallery/gallery_block.inc on line 36.
Компилятор avrgcc поддерживает C++, однако в его поставку не входит ни стандартная библиотека, ни реализация ABI: служебных функций, вызовы которых вставляет сам компилятор. В результате люди пытаются реализовать те части, которые им нужны, самостоятельно и зачастую делают это не очень хорошо. Например, часто предлагается отстрелить себе ногу определив пустую функцию __cxa_pure_virtual(void) {} или подложить себе грабли, написав заглушки для __cxa_guard_acquire, __cxa_guard_release и __cxa_guard_abort. В данной статье я предлагаю разобраться, чего не хватает для счастья, где это взять или как написать.
Я знаю, что немло людей считает, что C++ на микроконтроллере не нужен. Их я прошу прочитать последний раздел статьи перед тем, как писать комментарии.

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

Особенности для владельцев arduino

Arduino предоставляет ограниченную поддержку C++. Но, насколько я понимаю, разработчики arduino не любят C++, поэтому в соответсвующий модуль, по просьбам трудящихся, был вставлен первый попавшийся костыль. Им оказался костыль, описанный на avrfreaks, причем без исправлений, указанных в комментариях к топику. Поэтому сперва вам придется от него избавиться. Удалите файлы
  • hardware/arduino/cores/arduino/new.h
  • hardware/arduino/cores/arduino/new.cpp
Или используйте версию, где это уже сделано.

Чисто виртуальные и удаленные методы

Механизм виртуальных методов, как правило, реализуется через vtable. Это не регламентировано стандартом, однако используется во всех компиляторах. Даже если вы объявляете метод чисто виртуальным, то есть не имеющим реализации, в vtable все равно будет отведено место под указатель на этот метод. Это необходимо для того, чтобы у дочерних классов по этому же смещению положить указатель на соответсвующую реализацию. Вместо указателя на отсутствющий метод компилятор записывает в vtable указатель на функцию-заглушку __cxa_pure_virtual. Если кто-то сумеет вызвать чисто виртуальную функцию, то управление перейдет на заглушку и она остановит программу, вместо того, чтобы пытаться исполнить случайный кусок памяти. Обратите внимание, что эта защита обходится почти бесплатно: реализация __cxa_pure_virtual, содержащая единственный вызов, занимает всего 6 байт флеша.
Возникает резонный вопрос, а как вообще можно вызвать чисто виртуальную функцию, если нельзя создать объект абстрактного класса? Создать нельзя, а вызвать можно, если писать странный код:
class B {
public:
    B() {
        // Объект класса C пока не создан, поэтому используется vtable класса B
        // Однако в конструкторе не работает механизм виртуальных функций, поэтому
        // мы не можем вызвать не сущесутвющую функцию virt(), но можем вызвать
        non_virtual();
    }
 
    void non_virtual() {
        // Это обычная функция и она не знает, что вызвана из конструктора
        // поэтому она выполнит вызов виртуальной функции, причем вызовет
        // реализацию для класса B
        virt();
        // pure virtual method called
        // terminate called without an active exception
        // Аварийный останов (core dumped)
    }
 
    virtual void virt() = 0;
};
 
class C : public B{
public:
    virtual void virt() {}
};
 
int main(int argc, char** argv) {
    C c;
    return 0;
}
Чтобы не возникало таких ошибок, надо стараться не вызывать методы объекта, пока он не инициализирован. Другими словами, не надо делать сложную работу в конструкторе. А чтобы компилятор собрал ваше приложение, добавте реализацию следующих функций:
void __cxa_pure_virtual(void) {
    // We might want to write some diagnostics to uart in this case
    std::terminate();
}
 
void __cxa_deleted_virtual(void) {
    // We might want to write some diagnostics to uart in this case
    std::terminate();
}
Также вам понадобится реализация std::terminate из стандартной библиотеки. Если очень нужно экономить 2 байта оперативной памяти и 14 байт флеша, можно вызывать и abort() напрямую, однако позже я расскажу, почему std::terminate предпочтительнее.

Статические переменные

Вы можете объявить переменную внутри функции статической, что фактически сделает ее глобальной переменной видимой только внутри функции.
int counter(int start) {
    static int cnt = start;
    return ++cnt;
}
В C этот код не соберется, так как статическая переменная должна инициализироваться константой, чтобы сразу поместить начальное значение в секцию .data. В C++ это было разрешено, однако не специфицировалось, что произойдет в случае, если два потока попытаются инициализировать переменную одновременно. Многие компиляторы предпочли добавить блокировки и обеспечить потокобезопасность в этом случае, а в C++11 такое поведение стало частью стандарта. Поэтому инициализацию не константным значением статической переменной gcc развернет в следующий код: gcc/cp/decl.c
static <type> guard;
if (!guard.first_byte) {
    if (__cxa_guard_acquire (&guard)) {
        bool flag = false;
        try {
            // Do initialization.
            flag = true; __cxa_guard_release (&guard);
            // Register variable for destruction at end of program.
        } catch {
            if (!flag) __cxa_guard_abort (&guard);
        }
    }
}
где guard - целочисленный тип, достаточного размера чтобы хранить флаг и мьютекс. Просмотр исходников gcc показал, что его оптимизацией заморачивались только на ARM архитектуре:
gcc/config/arm/arm.c
/* The generic C++ ABI says 64-bit (long long).  The EABI says 32-bit.  */
static tree
arm_cxx_guard_type (void)
{
  return TARGET_AAPCS_BASED ? integer_type_node : long_long_integer_type_node;
}
Во всех остальных случаях используется тип по-умолчанию: long_long_integer_type_node. На avr, в зависимости от опции -mint8 он будет либо 64, либо 32 бита. Нам хватит и 16. guard.first_byte, в котором размещается флаг, понимается компилятором как байт с наименьшим адресом: *(reinterpret_cast(g)). Исключением является платформа ARM, где используется только один бит первого байта.

Как правильно?

Если вам не нужны потокобезопасные статические переменные, то отключите их опцией -fno-threadsafe-statics и компилятор вместо сложных блокировок поставит простую проверку флага. Реализовывать __cxa_guard_* в этом случае не нужно. Но если вы их предоставляете (как это сделано в arduino), то реализация должна обеспечивать корректную работу в случае одновременной инициализации переменной из обычного кода и из прерывания. Другими словами, __cxa_guard_acquire должна блокировать прерывания, а __cxa_guard_release и __cxa_guard_abort должны их возвращать к предыдущему состоянию. В случае использования RTOS я, возможно, готов пожертвовать корректностью в прерываниях, оставив корректность для двух потоков. Корректная реализация должна работать вот так:
namespace {
// guard is an integer type big enough to hold flag and a mutex. 
// By default gcc uses long long int and avr ABI does not change it
// So we have 32 or 64 bits available. Actually, we need 16.
 
inline char& flag_part(__guard *g) {
    return *(reinterpret_cast<char*>(g));
}
 
inline uint8_t& sreg_part(__guard *g) {
    return *(reinterpret_cast<uint8_t*>(g) + sizeof(char));
}
}
 
int __cxa_guard_acquire(__guard *g) {
    uint8_t oldSREG = SREG;
    cli();
    // Initialization of static variable has to be done with blocked interrupts
    // because if this function is called from interrupt and sees that somebody
    // else is already doing initialization it MUST wait until initializations
    // is complete. That's impossible.
    // If you don't want this overhead compile with -fno-threadsafe-statics
    if (flag_part(g)) {
        SREG = oldSREG;
        return false;
    } else {
        sreg_part(g) = oldSREG;
        return true;
    }
}
 
void __cxa_guard_release (__guard *g) {
    flag_part(g) = 1;
    SREG = sreg_part(g);
}
 
void __cxa_guard_abort (__guard *g) {
    SREG = sreg_part(g);
}


Сколько стоит

Если вы не используете статические переменные или присваиваете им константные значения - то бесплатно. Если вы указываете флаг -fno-threadsafe-statics, то платите 8 байт оперативной памяти за флаг, и 12 байт флеша на каждую переменную. Если же вы используете потокобезопасную инициализацию, потратите еще 38 байт флеша на каждую переменную и еще 44 на всю программу. Кроме того, на время инициализации статических переменных будут заблокированы прерывания. Но вы же не делаете сложную работу в конструкторах?
Выбор за вами, но в любом случае, если библиотека предоставляет функции __cxa_guard_*, они должны быть реализованы корректно, а не являться той затычкой, которую везде предлагают. А вообще, я рекомендовал бы стараться не использовать статические переменные.

Где взять

abi.h и abi.cpp

operator new и operator delete

Когда речь заходит об операторах new и delete обязательно кто-нибудь скажет, что в микроконтроллерах крайне мало памяти, поэтому динамическая память - непозволительная роскошь. Эти люди не знают, что new и delete - это не только управление динамической памятью. Есть еще placement new, располагающий объект в выделенном программистом буфере. Без него не напишешь любимый разработчиками встроенного ПО кольцевой буфер, через который реализуются очереди сообщений. Ну и если вы так уверены в том, что динамическая память не нужна, то зачем написали реализации для malloc и free? Значит есть задачи, где без них обойтись не получилось.

Типы операторов new и delete Во-первых, есть operator new выделяющий память под одиночные объекты и есть operator new[], выделяющий память под массивы. Технически они отличаются тем, что new[] запоминает размер массива, чтобы при удалении вызвать деструктор у каждого элемента. Поэтому важно при освобождении памяти использовать парный operator delete или operator delete[].
Во-вторых, каждый из этих операторов, как и любая функция в C++, может быть перегружен. И стандартом определены три варианта:
  1. void* operator new(std::size_t numBytes) throw(std::bad_alloc); выделит блок памяти размером numBytes. В случае ошибки кидает исключение std::bad_alloc
  2. void* operator new(std::size_t numBytes, const std::nothrow_t& ) throw(); выделит блок памяти размером numBytes. В случае ошибки возвращает nullptr
  3. inline void* operator new(std::size_t, void* ptr) throw() {return ptr; } placement new, располагает объект там, где сказали. Используется при реализации контейнеров
В arduino, по непонятным причинам, реализован только void* operator new(std::size_t numBytes) throw(std::bad_alloc), причем в случае ошибки он возвращает 0, что приводт к неопределенному поведению программы, так как возвращаемое значение никто не проверяет.
С operator delete все немного хитрее. Есть void* operator delete(std::size_t numBytes) и void* operator delete[](std::size_t numBytes). Вы можете его перегрузить для других параметров, но не можете вызвать эти перегрузки, так как в языке нет соответсвующего синтаксиса. Есть только один случай, когда компилятор вызовет перегруженные версии оператора delete. Представьте, что вы создаете объект в динамической памяти, оператор new успешно выделил память, ее начал заполнять конструктор и кинул исключение. Ваш код еще не получил в свое распоряжение указатель на объект, так что он не может вернуть системе память объекта-неудачника. Поэтому компилятор вынужден сам это сделать вызвав delete. Но что произойдет, если память "была выделена" с помощью placement new? В этом случае нельзя вызывать обычный delete, поэтому, если конструктор бросил исключение, компилятор вызовет перегруженную версию delete с теми же параметрами, с которыми был вызван new. Так что в стандартной библиотеке определено три версии operator delete и три версии operator delete[].

Обработка bad_alloc

Как было сказано выше, наиболее часто используемая версия new обязана кидать исключение, в случае ошибки. Но gcc не поддерживает исключения на avr: их нельзя ни кинуть, ни поймать. Но если их нельзя ловить, то в программе нет ни одной try секции, а значит, если бы исключение было кинуто, то вызвался бы std::terminate. Более того, стандарт C++ позволяет в таком случае (см. 15.5.1) не разматывать стек. Поэтому new может вызвать std::terminate напрямую и это будет соответствовать стандарту.
Не надо ужасаться, что стандартная библиотека возьмет и завершит прошивку! Часто ли вы можете что-то исправить, если произошел bad_alloc? Как правило, ничего. Ваша прошивка не может продолжать корректную работу и слава богу, что она завершится в момент возникновения ошибки. Но если вы знаете, как поправить ситуацию, вы можете воспользоваться nothrow версией оператора new. Посмотрите на это как на безопасный malloc, корректно себя ведущий в случае, если вы не проверяете возвращаемое им значение.

Где взять

В uClibc++ есть полная и корректная реализация new и delete. Правда вместо std::terminate там вызывается abort(). Поэтому я сделал исправленную версию. Заодно туда добавлены списки инициализации, std::move и std::forvard.

std::terminate vs abort()

Согласно документации на avr-libc, функция abort() блокирует все прерывания, после чего впадает в бесконечный цикл. Это не то, чего бы мне хотелось. По двум причинам. Во-первых, она оставляет устройство в опасном состоянии. Представьте, что система управляет нагревательным элементом и программа зациклится в момент, когда он включен. В случае ошибки я хочу перейти в безопасное состояние, установив все выходы платы в 0. Во-вторых, я уже знаю, что все плохо и мне не нужно дожидаться, пока сработает watchdog и перезагрузит систему. Это можно сделать немедленно.
Если прошивка завершается по std::terminate, я могу установить собственный обработчик и выполнить там все необходимые действия. Переопределить abort я не могу: механизм, предусмотренный для этого в unix не работает на avr. Поэтому я лучше потрачу те 2 байта оперативной памяти и 14 байт флеша, которые занимает реализация std::terminate.

Исключения

Исключения - та часть C++ за которую приходится платить много, причем не только в коде, который их использует напрямую, но и в коде, через который может пролететь исключение: компилятор вынужден регистрировать деструктор каждой переменной, создаваемой на стеке. Кроме того, для исключений нужен RTTI и небольшой резервный буфер памяти, чтобы было, где создать std::bad_alloc, когда память кончится. Кроме того, это единственная часть C++, для которой проблематично, хотя и не невозможно, рассчитать время выполнения. Насколько я понимаю, у любого, кто достаточно разбирался, чтобы написать недостающие на AVR функции поддержки работы исключений, пропадало желание это делать. Находится много более важных вещей, которые тоже надо сделать. Поэтому поддержки исключений на AVR в gcc нет и, вполне вероятно, что и не будет.

STL

Я видел много сообщений, что STL на микроконтроллере - это плохо: она раздувает код и, делая сложные вещи простыми, подстрекает ими пользоваться. При этом умалчивается, что в STL есть и такие примитивы, как быстрая сортировка, которая значительно быстрее и компактнее qsort, или бинарный поиск, безопасные версии min и max. Вы правда знаете сакральный способ написать классические алгоритмы эффективнее других программистов? А тогда почему бы не использовать готовый оттестированный алгоритм, который займет столько же места, сколько то, что вам придется написать. За те части STL, которые вы не используете, вы не платите.

Где взять

Используйте uClibc++. У этой библиотеки есть одна особенность: std::map и std::set реализованы поверх вектора, поэтому при вставках и удалениях итераторы инвалидируются. Кроме того, у них иная сложность. В документации автор подробно описывает, почему он так сделал.

Для чего нужен C++

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

Комментарии

!

Подробно все расписано, пригодилось. Спасибо

Мой отзыв

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

Очень интересный материал.

Очень интересный материал. Честно говоря, я представлял все это немного не так. В общем то я спасибо хотел сказать.





Мой отзыв

Материал на вашем сайте мне очень сильно понравился. Представить не мог, что быстро смогу найти ответ на вопрос. Спасибо огромное!!!.