当前位置: 首页 > 知识库问答 >
问题:

std::string[]成员解除分配在构造函数引发异常期间失败

丁安宜
2023-03-14

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

其中我有一个包含std::string[3]的类测试。测试的构造函数可能会抛出一个异常,我想在顶层(main)处理这个异常。然而,当从构造函数抛出时,xmemory中的断言失败了——在我看来,这似乎是在尝试释放和释放std::string[3]时发生的(请参阅下面的控制台输出和堆栈跟踪)。catch语句永远不会到达,在构建的版本中,它只是崩溃了。

当我用一个std::string替换std::string[3]时,catch语句就正确到达了。当从外部调用std::string作为另一个成员抛出时,也应使用std::string[3]。

这是怎么回事?感谢任何帮助。

最小的例子:

#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++

共有1个答案

松骏俊
2023-03-14

在评论者的帮助下,这很可能是默认成员初始值设定项和Visual Studio 2015的问题。

如果没有默认的初始值设定项,它就可以工作。

 类似资料:
  • 如果我构造一个空的使用默认的构造函数(和默认的分配器),它可以抛出一个异常吗? 通常,为容器的元素分配空间会引发异常(这将是一个<code>std::bad_alloc</code>)。但是<code>std::vector</code>的默认构造函数不需要分配任何这样的空间;它可以在第一次插入或分配时惰性地分配一些空间。但是C标准是否要求它不抛出异常(意味着延迟分配,或者捕获<code>std:

  • 问题内容: 允许构造函数抛出异常吗? 问题答案: 是的,构造函数可以引发异常。通常,这意味着新对象可以立即进行垃圾回收(当然,尽管一段时间内可能不会收集到)。如果“半构造”对象在构造函数中较早可见(例如,通过分配静态字段或将其自身添加到集合中),则可能会留下痕迹。 在构造函数中引发异常时要注意的一件事:由于调用者(通常)将无法使用新对象,因此构造函数应注意避免获取非托管资源(文件句柄等),然后引发

  • 问题内容: 如何从枚举构造函数中引发异常?例如: 产生错误 未处理的异常类型IOException 问题答案: 由于实例是在静态初始化程序中创建的,因此请抛出ExceptionInInitializerError。

  • 我有一个静态的方法,用于从PDF中获取标题,使用元数据通过itext,这是一个主要任务的一小部分。 我注意到一条令人费解的路径,我将其缩小到这段代码。具体来说,在我实例化PdfReader的行中,该过程不会抛出异常或继续到print语句。事实上,它清除了我所有的for循环,直到我的程序的顶层,并表现得好像什么都没发生,我的任务完成了。 除非我弄错了,否则在我的方法中执行这组代码时,“Reader实

  • -----------这是我的文件服务---------------------我使用的是spring boot 2.2.2 -------这是我的文件控制器-------- 进程已完成,退出代码为%1