Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用stringstream::imbue和自定义全局运算符new调试断言失败_C++_Windows_Assert_Stringstream - Fatal编程技术网

C++ 使用stringstream::imbue和自定义全局运算符new调试断言失败

C++ 使用stringstream::imbue和自定义全局运算符new调试断言失败,c++,windows,assert,stringstream,C++,Windows,Assert,Stringstream,我为这个相当本地化的问题道歉,但我希望得到其他人对它的看法,以确保我没有做明显错误的事情 我相信我在VisualC++运行时库中遇到了bug,或者在微软实现了代码< STD::StrugSuth中的某个地方。该问题仅在以下情况下出现: 调用imbue()来更改stringstream上的区域设置,并且 使用自定义全局运算符new,该运算符返回指针相对于malloc()返回的基址的偏移量,该基址用于分配块 我已经能够通过以下最小的测试用例重现这一点: #include <sstream>

我为这个相当本地化的问题道歉,但我希望得到其他人对它的看法,以确保我没有做明显错误的事情

<>我相信我在VisualC++运行时库中遇到了bug,或者在微软实现了代码< STD::StrugSuth中的某个地方。该问题仅在以下情况下出现:

  • 调用
    imbue()
    来更改
    stringstream
    上的区域设置,并且
  • 使用自定义全局
    运算符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;
    }
    
    #包括
    静态void*localMalloc(大小\u t字节)
    {
    unsigned char*ptr=static_cast(malloc(字节+64));
    ptr+=64;
    printf(“%d字节的malloc:%ph\n”,字节,ptr);
    返回ptr;
    }
    void*运算符new(大小为字节){返回localMalloc(字节);}
    void*运算符new[](大小为字节){return localMalloc(字节);}
    void运算符delete(void*ptr)throw(){/*不执行任何操作*/}
    void运算符delete[](void*ptr)throw(){/*不执行任何操作*/}
    结构小数分隔符:std::numpunct
    {
    char do_decimal_point()常量
    {
    返回“.”;
    }
    };
    int main()
    {
    std::stringstream-ss;
    imbue(std::locale(std::locale(),新的小数分隔符));
    
    ss这很可能不是一个bug,但是没有调用您的
    delete
    版本,而是调用Visual Studio的调试运行库的全局
    delete
    版本。在同一程序中有两个或多个版本的全局
    delete
    操作符是未定义的行为

    从中,发生这种情况时,行为被声明为未定义

    <>从C++ ISO标准:

    3.7.4动态存储持续时间[基本stc动态]
    //

    §2库为全局分配提供默认定义 和释放函数。一些全局分配和释放 函数是可替换的(18.61.)。<强> C++程序应提供AT 可替换分配或解除分配的最简单定义 功能。


    使用Visual Studio runtime library发布版本运行Visual Studio 2015不会产生此错误,并且实际上会调用替换的全局
    delete


    旁注:编译器保留名称
    \u localMalloc
    :@DieterLücking很好,忘了这一点。我已删除下划线并再次测试,以确保它不是问题。请运行发布版本而不是调试版本。当运行调试版本时,您的代码的行为可能由于调试而未定义运行时调用自己版本的
    delete
    ,执行检查并查看您的指针是否无效。@PaulMcKenzie我自己也期望类似的结果,但它在发布模式下也会崩溃:
    未处理的异常位于…(ucrtbase.dll)在test.exe中:请求致命程序退出。
    因此CRT中有东西正在调用
    abort()
    ,也许?与在线VC++编译器不一样。我也用你的代码并用VS 2015编译了一个发布版本——没有崩溃。是的,看起来就是这样。如果我改变代码生成选项以静态链接CRT而不是使用DLL,断言将不再发生。因此基本上是UB来代替全局
    operator delete
    在任何动态链接到CRT的程序中?所有其他应用程序如何处理此问题?我猜其他应用程序都知道这一点,并且不使用调试运行库。啊,好的,所以只有调试CRT取代了
    operator delete
    ?在这种情况下,我可以使用带有调试配置的静态链接ns,但仍然使用动态链接和发布配置?我认为应该可以(除非其他人插话),因为要使用的运行库是编译设置(而不是链接器设置)在VisualC++中,如果存在错误,那么它们会显示为链接器错误。但是,如果在同一个程序中确实有两个或更多个全局代码>删除>代码>函数,则它是未定义的行为。