Почему переопределенный оператор new не вызывает? - PullRequest
3 голосов
/ 24 ноября 2011

Я запускаю следующий код на VS2005:

#include <iostream>
#include <string>
#include <new>
#include <stdlib.h>

int flag = 0;

void* my_alloc(std::size_t size)
{
    flag = 1;
    return malloc(size);
}

void* operator new(std::size_t size) { return my_alloc(size); }
void operator delete(void* ptr) { free(ptr); }
void* operator new[](std::size_t size) { return my_alloc(size); }
void operator delete[](void* ptr) { free(ptr); }

int main()
{
    std::string str;
    std::getline(std::cin, str);
    std::cout << str;
    return flag;
}

Я ввожу достаточно длинную строку (длиннее буфера для оптимизации маленьких строк):

0123456789012345678901234567890123456789012345678901234567890123456789

В компиляции Debug процесс возвращает 1, в конфигурации Release процесс возвращает 0, что означает, что новый оператор не вызывается! Я могу проверить это, поставив точку останова, записав в выходной / отладочный вывод и т. Д. *

Почему это так, и это стандартное поведение, соответствующее?

Ответы [ 4 ]

5 голосов
/ 24 ноября 2011

После некоторого исследования то, что @ bart-jan написал в своем втором ответе (который сейчас удален, хотя никто не проголосовал за него), на самом деле является правильным.

Как легко видеть, мой оператор вообще не вызывается в Release, вместо этого вызывается версия CRT. (И нет, для всех тех, кто стрелял в темноте, здесь нет рекурсии.) Вопрос «почему?»

Выше было скомпилировано с динамически связанным CRT (который используется по умолчанию). Microsoft обеспечивает создание экземпляра std :: string (среди многих других стандартных шаблонов) в DLL-библиотеке CRT. Просмотр заголовков Dinkumware, поставляемых с VS2005:

#if defined(_DLL_CPPLIB) && !defined(_M_CEE_PURE)

template class _CRTIMP2_PURE allocator<char>;
// ...
template class _CRTIMP2_PURE basic_string<char, char_traits<char>,
    allocator<char> >;

Где _CRTIMP2_PURE расширяется до __declspec(dllimport). Это означает, что в Release компоновщик связывает std::string с версией, которая была создана при создании CRT, которая использует реализацию по умолчанию new.

Непонятно, почему этого не происходит при отладке. Как правильно понял @Violet Giraffe, некоторые переключатели должны повлиять на него. Однако я думаю, что это переключатели компоновщика, а не переключатели компилятора. Я не могу найти, какой именно переключатель имеет значение.

Другой левый вопрос, который все здесь игнорировали, это "это стандарт"? Пробуя код в VS2010, он действительно называется моим operator new независимо от того, какую конфигурацию я компилирую! Поиск в заголовках, поставляемых с VS2010, показывает, что Dinkumware удалил __declspec(dllimport) для вышеупомянутой реализации. Таким образом, я считаю, что старое поведение действительно является ошибкой компилятора, а не стандарт.

0 голосов
/ 24 ноября 2011

Вы действительно должны пошагово отлаживать код.Вы пытались установить / Od в своей конфигурации релиза, чтобы отключить оптимизацию?Интересно, изменит ли это поведение?

0 голосов
/ 24 ноября 2011

У вас бесконечная рекурсия.

Вместо этого сделайте как

#include <iostream>
#include <string>
#include <new>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>

void* my_alloc( char const* str, std::size_t size )
{
    fprintf( stderr, "%s %lu\n", str, (unsigned long)size );
    return malloc( size ); // I don't care for errors here
}

void* operator new( std::size_t size )      { return my_alloc( "new", size ); }
void operator delete( void* ptr )           { free(ptr); }
void* operator new[]( std::size_t size )    { return my_alloc( "new[]", size ); }
void operator delete[]( void* ptr )         { free( ptr ); }

int main()
{
    std::string str;
    std::cout << "? ";
    std::getline(std::cin, str);
    std::cout << str;
}
0 голосов
/ 24 ноября 2011

Вызов cout << std :: string () из вашего нового оператора или одной из вызванных функций внутри вызовет непредсказуемое поведение программы.Не используйте io от вашего нового оператора.Подобные действия могут повторно ввести вашего нового оператора.</p>

...