我为这个相当本地化的问题道歉,但我希望得到别人对此的看法,以确保我没有做出明显错误的事情。
我相信我在Visual C ++运行时库或Microsoft的std::stringstream
实现中遇到了一个错误。这个问题只表现在以下几个方面:
imbue()
来更改stringstream
和operator new
,其中返回指针偏移量,该指针偏离用于分配块的malloc()
返回的基址。 我已经能够使用以下最小测试用例重现这一点:
#include <sstream>
static void *localMalloc(size_t bytes)
{
unsigned char *ptr = static_cast<unsigned char *>( malloc(bytes + 64) );
ptr += 64;
printf("malloc of %d bytes: %ph\n", bytes, ptr);
return ptr;
}
void *operator new(size_t bytes) { return localMalloc(bytes); }
void *operator new[](size_t bytes) { return localMalloc(bytes); }
void operator delete(void *ptr) throw() { /* do nothing */ }
void operator delete[](void *ptr) throw() { /* do nothing */ }
struct DecimalSeparator : std::numpunct<char>
{
char do_decimal_point() const
{
return '.';
}
};
int main()
{
std::stringstream ss;
ss.imbue(std::locale(std::locale(), new DecimalSeparator));
ss << 5; // <-- is_block_type_valid(header->_block_use) assertion failure here
return 0;
}
如果:
ptr += 64;
或localMalloc()
行
ss.imbue()
main()
来电
醇>
被注释掉,代码按预期工作,并且断言不会发生。
我试图尽可能多地使用调试器进入代码,但我目前无法确定代码在STL中失败的位置,因为Visual Studio在退出后将我转储到原始反汇编模式basic_stringbuf::overflow()
使调试几乎不可能。据我所知,我没有看到在分配的内存之外有任何无效的内存写入,所以我不完全确定CRT在哪里检查堆或者它认为指针无效的原因。
请注意,operator delete
在此测试用例中故意忽略free以简化。如果在内存块上正确调用free()
,则没有区别。
到目前为止,对以下编译器和平台的测试已导致:
有没有人在这里看到我错过的任何奇怪的东西?
答案 0 :(得分:1)
这很可能不是一个错误,而是调用了您的delete
版本,而是调用了Visual Studio的调试运行时库的全局delete
版本。在同一程序中有两个或更多版本的全局delete
运算符是未定义的行为。
从this reference (Global replacements)开始,当发生这种情况时,表明行为是未定义的。
来自C ++ ISO标准:
3.7.4动态存储持续时间[basic.stc.dynamic]
//...§2该库提供全局分配的默认定义 和释放功能。一些全局分配和解除分配 功能是可替换的(18.6.1)。 C ++程序应提供at 可替换分配或释放的大多数定义 功能强>
使用版本Visual Studio运行时库运行Visual Studio 2015不会产生此错误,实际上替换全局delete
会被调用。