Оптимизация небольших строк (режим отладки и выпуска) - PullRequest
1 голос
/ 16 февраля 2020

Я изучал оптимизацию небольших строк (в MSV C 2019) с использованием этого примера сценария:

#include <string>

void* operator new(size_t size)
{
    std::printf("global op new called, size = %zu\n", size);
    void* ptr = std::malloc(size);

    if (ptr)
        return ptr;
    else
        throw std::bad_alloc{};
}

int main()
{
    std::string test = "small value";
    return 0;
}

Обратите внимание, я взял void* operator new(size_t size) из https://en.cppreference.com/w/cpp/memory/new/operator_new.

В режиме Release оптимизация работает должным образом (т. Е. new не вызывается), но в режиме Debug скрипт фактически печатает global op new called, size = 16 , После детализации это, кажется, связано с этим сегментом кода в заголовке xmemory:

#if _ITERATOR_DEBUG_LEVEL == 0
  #define _GET_PROXY_ALLOCATOR(_Alty, _Al) _Fake_allocator()
  template <class _Alloc>
  using _Container_proxy_ptr = _Fake_proxy_ptr_impl;
#else // _ITERATOR_DEBUG_LEVEL == 0
  #define _GET_PROXY_ALLOCATOR(_Alty, _Al) static_cast<_Rebind_alloc_t<_Alty, _Container_proxy>>(_Al)
  template <class _Alloc>
  using _Container_proxy_ptr = _Container_proxy_ptr12<_Rebind_alloc_t<_Alloc, _Container_proxy>>;
#endif // _ITERATOR_DEBUG_LEVEL == 0

Мы можем видеть, что в режиме Release (т.е. _ITERATOR_DEBUG_LEVEL == 0) мы используем _Fake_proxy_ptr_impl, тогда как в режиме Debug мы используем _Container_proxy_ptr12, который использует new.


Мой вопрос прост: почему существует такая разница между Debug и выпуск режим?

1 Ответ

1 голос
/ 16 февраля 2020

Оптимизация небольших строк все еще существует и в режиме отладки. Если мы создадим string

std::string test = "large value.large value.large value.large value.";

большего размера, то получим фактическое string распределение

global op new called, size = 64

в сборках Debug и Release.

Что вы Вы наблюдаете за выделением прокси-контейнера для отладки итератора (как видно из #if _ITERATOR_DEBUG_LEVEL)

struct _Container_proxy { // store head of iterator chain and back pointer

Вы можете отключить отладку итератора, построив с помощью /D _ITERATOR_DEBUG_LEVEL=0 ( но тогда он будет отключен для всех контейнеров, а также для vector, map et c.).

...