Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Error in MSVC 2017...

27 views
Skip to first unread message

Chris M. Thomasson

unread,
Nov 7, 2019, 5:48:08 PM11/7/19
to
This damn error still persists. MSVC needs to fix it. Have not checked
the 2019 version yet. It has to do with reporting the size of an
allocated array using overloaded new and delete. Here is the code:
______________________________
#include <cstdio>
#include <new>

struct custom_allocator {
static void* allocate(std::size_t size) {
void* const mem = ::operator new(size);
std::printf("custom_allocator::allocate(%p, %lu)\n",
(void*)mem, (unsigned long)size);
return mem;
}

static void deallocate(void* const mem, std::size_t size) {
std::printf("custom_allocator::deallocate(%p, %lu)\n",
(void*)mem, (unsigned long)size);
::operator delete(mem);
}
};


template<typename T>
struct allocator_base {
static void* operator new(std::size_t size) {
return custom_allocator::allocate(size);
}

static void* operator new[](std::size_t size) {
return custom_allocator::allocate(size);
}

static void operator delete(void* mem) {
if (mem) {
custom_allocator::deallocate(mem, sizeof(T));
}
}

static void operator delete [](void* mem, std::size_t size) {
if (mem) {
custom_allocator::deallocate(mem, size);
}
}
};


template<std::size_t T_size>
class buf {
char mem[T_size];
};


class buf2 : public buf<1234>, public allocator_base<buf2> {
char mem2[1000];
};


int main() {
buf2* b = new buf2;
delete b;

b = new buf2[5];
delete [] b;

return 0;
}
______________________________


MSVC gives the following erroneous output:
____________________________
custom_allocator::allocate(0126A478, 2234)
custom_allocator::deallocate(0126A478, 2234)
custom_allocator::allocate(0126CFF0, 11170)
custom_allocator::deallocate(0126CFF0, 2234)
____________________________


Notice that MSVC loses the size of the dynamic array!? Grrr.... However,
GCC still gets its right:
____________________________
custom_allocator::allocate(00df7320, 2234)
custom_allocator::deallocate(00df7320, 2234)
custom_allocator::allocate(00df7320, 11174)
custom_allocator::deallocate(00df7320, 11174)
____________________________

This has been a persistent bug in MSVC for a long time. I wonder how
many crashes it caused over the years? Hopefully not a lot because this
usage is fairly rare...

Melzzzzz

unread,
Nov 7, 2019, 6:07:04 PM11/7/19
to
Try array of objects with destructors. With destructors they have to
place number of objects in array, so then it is possiblity they will
report correct size...

--
press any key to continue or any other to quit...
U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec
Svi smo svedoci - oko 3 godine intenzivne propagande je dovoljno da jedan narod poludi -- Zli Zec
Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi
bili naoruzani. -- Mladen Gogala

Chris M. Thomasson

unread,
Nov 7, 2019, 6:38:47 PM11/7/19
to
On 11/7/2019 3:06 PM, Melzzzzz wrote:
> On 2019-11-07, Chris M. Thomasson <chris.m.t...@gmail.com> wrote:
>> This damn error still persists. MSVC needs to fix it. Have not checked
>> the 2019 version yet. It has to do with reporting the size of an
>> allocated array using overloaded new and delete. Here is the code:
[...]
>> Notice that MSVC loses the size of the dynamic array!? Grrr.... However,
>> GCC still gets its right:
>> ____________________________
>> custom_allocator::allocate(00df7320, 2234)
>> custom_allocator::deallocate(00df7320, 2234)
>> custom_allocator::allocate(00df7320, 11174)
>> custom_allocator::deallocate(00df7320, 11174)
>> ____________________________
>>
>> This has been a persistent bug in MSVC for a long time. I wonder how
>> many crashes it caused over the years? Hopefully not a lot because this
>> usage is fairly rare...
> Try array of objects with destructors. With destructors they have to
> place number of objects in array, so then it is possiblity they will
> report correct size...
>

Okay. Wrt the following code:
struct foo : public allocator_base<foo>
{
foo() { std::printf("(%p)->foo::foo()\n", (void*)this); }
~foo() { std::printf("(%p)->foo::~foo()\n", (void*)this); }

int a;
char b[10];
double c;
};


int main() {
buf2* b = new buf2;
delete b;

b = new buf2[5];
delete [] b;

foo* f = new foo[3];
delete [] f;

return 0;
}

________________________


On GCC I get the following output:
________________________
custom_allocator::allocate(00977320, 2234)
custom_allocator::deallocate(00977320, 2234)
custom_allocator::allocate(00977320, 11174)
custom_allocator::deallocate(00977320, 11174)
custom_allocator::allocate(00977320, 80)
(00977328)->foo::foo()
(00977340)->foo::foo()
(00977358)->foo::foo()
(00977358)->foo::~foo()
(00977340)->foo::~foo()
(00977328)->foo::~foo()
custom_allocator::deallocate(00977320, 80)
________________________


On MSVC 2017, I get:
________________________
custom_allocator::allocate(00C8A4C8, 2234)
custom_allocator::deallocate(00C8A4C8, 2234)
custom_allocator::allocate(00C8CFF0, 11170)
custom_allocator::deallocate(00C8CFF0, 2234)
custom_allocator::allocate(00C85D98, 76)
(00C85D9C)->foo::foo()
(00C85DB4)->foo::foo()
(00C85DCC)->foo::foo()
(00C85DCC)->foo::~foo()
(00C85DB4)->foo::~foo()
(00C85D9C)->foo::~foo()
custom_allocator::deallocate(00C85D98, 76)
________________________

Humm... Using the dtor forced MSVC to get it right wrt returning the
same size for a deallocation of an array. It still errors on the first
case. Interesting wrt the original allocation size and deallocation
sizes not matching. Thanks Melzzzzz. :^)

Also notice the difference between GCC:

custom_allocator::allocate(00977320, 11174)
custom_allocator::deallocate(00977320, 11174)

and MSVC:

custom_allocator::allocate(00C8CFF0, 11170)
custom_allocator::deallocate(00C8CFF0, 2234)


The 80 - 76 = 4 aspect wrt GCC and MSVC is interesting as well wrt the
size of the dynamic array. It seems like GCC uses 4 extra bytes because
2234 * 5 = 11170. I wonder if extra data allows it to get the correct
size on array deallocation. Humm...

Chris Vine

unread,
Nov 9, 2019, 10:10:57 AM11/9/19
to
On Thu, 7 Nov 2019 14:47:55 -0800
"Chris M. Thomasson" <chris.m.t...@gmail.com> wrote:
> This damn error still persists. MSVC needs to fix it. Have not checked
> the 2019 version yet. It has to do with reporting the size of an
> allocated array using overloaded new and delete. Here is the code:

Microsoft have said they are not going to the fix the two argument
version of operator delete[]. They recognize their compiler is not
standard compliant, but to fix it would break code (including their
own).

The best thing with windows is not to customize operator new[]/delete[],
or if you do to allocate a block of memory four bytes larger than the
request, store the size of the array as the first four bytes of the
allocation and use that to obtain the size of the memory block
for operator delete[] (which also means operator new[] returning memory
offset by four bytes, which may have alignment consequences - make it
larger if need be).

Manfred

unread,
Nov 9, 2019, 1:19:14 PM11/9/19
to
Could you give any reference?

Chris Vine

unread,
Nov 9, 2019, 5:29:14 PM11/9/19
to
Ten or so years ago I could have. There was a visual studio problem
report in which that answer was given. At that time the problem was
fairly widely discussed.

If you use visual studio and want to be told again (or can't find the
earlier PR, I now can't but I can't say I have looked that hard) then
make another problem report and be told again. It is straightforward
to come up with a code example to illustrate the defect.
0 new messages