【问题标题】:std::string[] member deallocation fails during exception thrown from constructorstd::string[] 成员释放在构造函数抛出异常期间失败
【发布时间】:2019-05-20 06:53:50
【问题描述】:

使用 Visual Studio 2015(更新 3)我在一个较大的项目中遇到问题,我将其归结为下面的最小示例。

其中我有一个包含 std::string[3] 的类 Test。可能会发生,Test 的构造函数抛出异常,我想在顶层(主)处理。但是,当从构造函数中抛出时,xmemory 中的断言失败 - 在我看来,在尝试展开和解除分配 std::string[3] 时(请参阅下面的控制台输出和堆栈跟踪)。永远不会到达 catch 语句,并且在构建的版本中它只会崩溃。

当我用单个 std::string 替换 std::string[3] 时,会正确到达 catch 语句。此外,当构造完成后从外部调用的另一个成员函数抛出异常时,如果使用 std::string[3],将按预期到达 catch 块。

这是怎么回事? 任何帮助表示赞赏。

最小的例子:

#include "stdafx.h"
#include <vcruntime_exception.h>
#include <string>
#include <iostream>



class Test {
public:
    Test() {
        // throw exception from constructor
        throw std::exception("TestException");
    }

    ~Test() {
        std::cout << "Destruction" << std::endl;
    }

    //std::string mySingleString = "SingleTestString";
    std::string myStrings[3] = { "String1", "TestString2", "AnotherTestString" };
};


int main()
{
    try
    {
        Test* t = new Test();
    }
    catch (std::exception& e)
    {
        // this is never reached while std::string myStrings is not uncommented
        std::cout << "Caught:" << e.what() << std::endl;
    }
    catch (...) {
        std::cout << "Caught an alien!" << std::endl;
    }
    return 0;
}

控制台输出:

Ausnahme ausgelöst bei 0x773CDDC2 in ConsoleApplication1.exe: Microsoft C++-Ausnahme: std::exception bei Speicherort 0x0019FB8C.
"ConsoleApplication1.exe" (Win32): "C:\Windows\SysWOW64\kernel.appcore.dll" geladen. Symbole wurden geladen.
"ConsoleApplication1.exe" (Win32): "C:\Windows\SysWOW64\msvcrt.dll" geladen. Symbole wurden geladen.
"ConsoleApplication1.exe" (Win32): "C:\Windows\SysWOW64\rpcrt4.dll" geladen. Symbole wurden geladen.
"ConsoleApplication1.exe" (Win32): "C:\Windows\SysWOW64\sspicli.dll" geladen. Symbole wurden geladen.
"ConsoleApplication1.exe" (Win32): "C:\Windows\SysWOW64\cryptbase.dll" geladen. Symbole wurden geladen.
"ConsoleApplication1.exe" (Win32): "C:\Windows\SysWOW64\bcryptprimitives.dll" geladen. Symbole wurden geladen.
"ConsoleApplication1.exe" (Win32): "C:\Windows\SysWOW64\sechost.dll" geladen. Symbole wurden geladen.
Debug Assertion Failed!

Program: ...15\Projects\ConsoleApplication1\Debug\ConsoleApplication1.exe
File: c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0
Line: 100

Expression: "(_Ptr_user & (_BIG_ALLOCATION_ALIGNMENT - 1)) == 0" && 0

堆栈跟踪:

ConsoleApplication1.exe!std::_Deallocate(void * _Ptr, unsigned int _Count, unsigned int _Sz) Zeile 99   C++
ConsoleApplication1.exe!std::allocator<char>::deallocate(char * _Ptr, unsigned int _Count) Zeile 720    C++
ConsoleApplication1.exe!std::_Wrap_alloc<std::allocator<char> >::deallocate(char * _Ptr, unsigned int _Count) Zeile 988 C++
ConsoleApplication1.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy(bool _Built, unsigned int _Newsize) Zeile 2260  C++
ConsoleApplication1.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> >() Zeile 1018 C++
ConsoleApplication1.exe!`eh vector destructor iterator'(void * ptr, unsigned int size, unsigned int count, void(*)(void *) destructor)  C++
ConsoleApplication1.exe!_main() C++
ConsoleApplication1.exe!main() Zeile 27 C++

【问题讨论】:

  • 首先,这不是我的代码,其次为什么不是?
  • 听起来像一个编译器错误。 std::array&lt;std::string, 3&gt; 可能会解决这个问题。
  • 不使用默认成员初始化器会不会发生这种情况?
  • 无法使其与成员初始值设定项列表一起使用。同样的错误。
  • 如果你在某处违反规则,我看不到。我用 MSVC 2015 Update 3 重复了这个问题。不要让 2017 在任何我可以尝试的地方启动。

标签: c++ exception visual-c++ try-catch stdstring


【解决方案1】:

在评论者的帮助下,这很可能是默认成员初始化程序和 Visual Studio 2015 的问题。

没有默认初始化器也可以工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 2014-04-03
    • 1970-01-01
    • 2011-11-04
    • 2010-09-13
    相关资源
    最近更新 更多