Оператор новой перегрузки в windows - PullRequest
3 голосов
/ 19 мая 2011

Я пытаюсь заменить глобальный оператор новым и удалить.В Linux это работает нормально, но в Windows (MSVC 10) он иногда выделяется с использованием системной версии оператора new, а затем пытается освободить его с помощью моего оператора delete.Поскольку я храню некоторую контекстную информацию во время выделения, мой оператор delete ожидает то же самое во время освобождения.Как я могу быть уверен, что Windows постоянно обновляет мой оператор?

edit: я пробовал разные вещи.Это декларация

//Global new and delete overload
void* operator new (std::size_t bytes) throw(...);
void operator delete(void* p) throw();

void* operator new( std::size_t size, const std::nothrow_t&) throw();
void operator delete( void* mem, const std::nothrow_t&) throw();

void* operator new[] ( std::size_t bytes) throw(...);
void operator delete[](void* p) throw();

void* operator new[]( std::size_t size, const std::nothrow_t&) throw();
void operator delete[](void* mem, const std::nothrow_t&) throw();

#ifdef WIN32
void *__CRTDECL operator new(std::size_t size) _THROW1(_STD bad_alloc);
#endif

Это определения

#ifdef WIN32
void *__CRTDECL operator new(std::size_t bytes) _THROW1(_STD bad_alloc)
{
    void* p = edb::g_getCurrentMemoryContext()->alloc(bytes);
    if (p==0) // did malloc succeed?
        throw std::bad_alloc(); // ANSI/ISO compliant behavior
    return p;
}

#endif

void operator delete(void* p) throw()
{
    edb::MemContext::free(p);
}

void* operator new( std::size_t bytes, const std::nothrow_t&) throw()
{
    return edb::g_getCurrentMemoryContext()->alloc(bytes);
}

void operator delete(void* p, const std::nothrow_t&) throw()
{
    edb::MemContext::free(p);
}

void* operator new[] ( std::size_t bytes) throw(...)
{
    void* p = edb::g_getCurrentMemoryContext()->alloc(bytes);
    if (p==0) // did malloc succeed?
        throw std::bad_alloc(); // ANSI/ISO compliant behavior
    return p;
}

void operator delete[](void* p) throw()
{
    edb::MemContext::free(p);
}

void* operator new[]( std::size_t bytes, const std::nothrow_t&) throw()
{
    return edb::g_getCurrentMemoryContext()->alloc(bytes);
}

void operator delete[](void* p, const std::nothrow_t&) throw()
{
    edb::MemContext::free(p);
}

И иногда она подхватывает мои определения, а иногда нет.

Спасибо, Гокул.

1 Ответ

7 голосов
/ 19 мая 2011

Переопределение глобального нового / удаления в C ++ - это tar baby . Да, это выглядит достаточно просто, но затем вы делаете одно исключение за другим, и вы продолжаете копать все глубже и глубже для себя.

Причина, по которой вы получаете «их новые» и «ваши удаления», заключается в том, что вы, вероятно, используете некую DLL, которая уже загружена и «связана» с существующей новой до загрузки вашей. Они выделяют объект, а затем вы должны удалить его. Вы можете попробовать статически связать вашу программу, чтобы решить эту проблему.

Еще один способ справиться с этим - это реорганизовать ваш код и переопределить новый / удалить как базовый класс, а затем сделать так, чтобы все ваши классы наследовали от него. Утомительно для большого проекта с большим количеством классов, но он будет недвусмысленно определять, для кого вызывается new / delete.

Если вы делаете это как «дешевый» способ изоляции утечки памяти, подумайте о другом. Посмотрите, есть ли у кого-либо из поставщиков инструментальных средств (например, очистить) пробная версия на 2 недели или запустите вашу версию Linux через valgrind .

...