2

I expect next code works. And do not introduce memory leak. I test it in three compilers, and it fails with Microsoft Visual Studio 2017 (15.4.5) I try also in online compiler (http://rextester.com/l/cpp_online_compiler_visual) and receive same fail. Next code work nice in clang++6.0 and g++8.2 but in msvc2017 as I see there is a memory leak. Why is so? Should I report bug to Microsoft, and what c++ standard say about it?

#include <cassert>
#include <iostream>
#include <cstdlib>
#include <new>

int global_counter = 0;

void * operator new(std::size_t n) noexcept(false) // _THROW_BAD_ALLOC // 
throw(std::bad_alloc) 
{
    void* result = malloc(n);
    ++global_counter;
    return result;
}
void operator delete(void * p) noexcept(true)
{
    free(p);
    --global_counter;
}
void operator delete(void* p, std::size_t) noexcept(true)
{
    free(p);
    --global_counter;
}

struct A
{
    A(int i)
        :value(i){
            std::cout << "constructor A" << std::endl;
        }
    ~A()noexcept(false){throw value;}

    int value;
};

int main()
{
    int start_value = global_counter;
    std::cout << "start global_counter = " << global_counter << std::endl;
    {
        try
        {
            //A a1();
            A* a2{new A(2)};
            std::cout << "before ex global_counter = " << global_counter << std::endl;
            delete a2;
        } catch (int i)
        {
            std::cout << "in catch ex global_counter = " << global_counter << std::endl;
            std::cout << "exception value: " << i << std::endl;
        }
    }
    std::cout << "end global_counter = " << global_counter << std::endl;
    assert(global_counter == start_value);
    return 0;
}

compile command for msvc:

cl.exe source_file.cpp -o a.exe /EHsc /MD /link /std:c++17

compile command for g++(linux):

g++ prog.cc -Wall -Wextra -std=gnu++2a

compile command for clang++(linux):

clang++ prog.cc -Wall -Wextra -std=gnu++2a
leanid.chaika
  • 2,143
  • 2
  • 27
  • 30
  • I didn't see delete operator called before or after exception, so assert is triggered. – leanid.chaika Sep 18 '18 at 13:59
  • 2
    Unrelated to your question, but you do know that the `throw` specifier have been deprecated since C++11, and with a non-empty specifier have been removed from the C++17 specification? Furthermore, the `malloc` function will never throw C++ exceptions. And lastly, your code isn't thread-safe. – Some programmer dude Sep 18 '18 at 13:59
  • 2
    This seems to be a compiler bug. – François Andrieux Sep 18 '18 at 14:04
  • 2
    @Someprogrammerdude Using "you do know that ...?" is a demeaning way of informing someone. It suggests disbelief that someone might not know something. Even "common knowledge" has to be learned [at some point](https://xkcd.com/1053/). – François Andrieux Sep 18 '18 at 14:07
  • 2
    @FrançoisAndrieux That's not my intent, and to the OP if you took it badly I'm sorry. – Some programmer dude Sep 18 '18 at 14:44

0 Answers0