代码之家  ›  专栏  ›  技术社区  ›  laura

无法捕获std::无效的\u参数

  •  1
  • laura  · 技术社区  · 17 年前

    我遇到了一个问题,它捕获了一个std::invalid_参数异常,我无法跟踪它。我使用的是GCC4.4.0(Windows),pthreads-win32 2.8.0的gc2 dll。

    基本上,从两个线程(主线程和一个开始使用pthread_create的线程)开始,我尝试大致同时创建一个类A的实例。构造函数抛出了一个std::invalid_参数,但它被应捕获异常的try/catch块包围。但是,这种情况不会发生(非常罕见的是,只有一个线程可能会捕获异常——但没有规则说明哪一个线程会捕获异常)

    如果我试图只在其中一个线程上创建对象,那么这个创建将按它应该的方式工作,并捕获异常。如果我在不同的时间创建这两个对象,那么create将按它应该的方式工作,并捕获异常。如果我试图同时创建它们,则会调用:::terminate()。

    也许有人知道为什么会发生这种情况(我已经排除了标题):

    void *run(void *ptr)
    {
        Sleep(5000);
        try
        {
            A *a = new A(5);
            a->a = 12;
        }
        catch (std::exception &ex)
        {
            printf("t - %s\n", ex.what());
        }
        return NULL;
    }
    
    int main(void) {
        pthread_t t;
        if (pthread_create(&t, NULL, run, NULL) != 0)
        {
            printf("No thread\n");
        }
        else
        {
            Sleep(5000);
            try
            {
                A *a = new A(5);
                a->a = 13;
            } catch (std::exception &ex)
            {
                printf("M - %s\n", ex.what());
            }
            pthread_join(t, NULL);
        }
        return 0;
    }
    
    class A
    {
    public:
        A(int a);
        virtual ~A();
        int a;
    };
    A::A(int a)
    {
        throw std::invalid_argument("Invalid!");
    }
    A::~A(){}
    

    生成文件是:

    CXXFLAGS = -O0 -g -Wall -Werror -fmessage-length=0
    OBJS =  WOpenTest.o A.o
    INCL = -I../pthreads-win32/include 
    LIBS =   -lws2_32 -lgdi32 -lpthreadGC2 
    LIB_DIRS =  -L ../pthreads-win32/lib 
    TARGET = WOpenTest.exe
    $(TARGET): $(OBJS)
     $(CXX) -o $(TARGET) $(OBJS) $(LIBS) $(LIB_DIRS) $(INCL)
    WOpenTest.o : WOpenTest.cpp
     g++ $(CXXFLAGS) -c WOpenTest.cpp $(INCL)  
    A.o : A.cpp A.h
     g++ $(CXXFLAGS) -c A.cpp $(INCL)
    all: $(TARGET)
    clean:
     rm -f $(OBJS) $(TARGET)
    

    我看到的输出是:

    (最常见)$/wopentest.exe

    此应用程序已请求 运行时在异常情况下终止 方式。请联系申请者 支持团队了解更多信息。

    此应用程序已请求 运行时在异常情况下终止 方式。请联系申请者 支持团队了解更多信息。 在引发 “std::invalid”的实例 递归调用的终止

    美元/wopentest.exe

    此应用程序已请求 运行时在异常情况下终止 方式。请联系申请者 支持团队了解更多信息。 M -无效!

    美元/wopentest.exe

    此应用程序已请求 运行时在异常情况下终止 方式。请联系申请者 支持团队了解更多信息。 T -无效!

    此应用程序已请求 运行时在异常情况下终止 方式。请联系申请者 支持团队了解更多信息。

    此应用程序已请求 运行时在异常情况下终止 方式。请联系申请者 支持团队了解更多信息。 在引发 “std::invalid”的实例
    what():无效!

    对我应该做什么有什么想法吗?或者是我在pthreads上找不到的东西?

    4 回复  |  直到 17 年前
        1
  •  2
  •   Rob Kennedy    17 年前

    您已经得出结论,这与混合链接到的单线程库有关。我找到一页关于 configuring NetBeans to use MinGW ,它在“使用POSIX线程进行多线程处理”部分下面有以下建议:

    • 如果使用异常处理,则很重要:使用附加的编译器开关“-mthreads”编译应用程序。否则,异常处理将无法可靠工作,并且可能发生不特定的崩溃。将异常从DLL传播到应用程序时,可能会出现其他问题。我在网络中发现了一些与此相关的提示,但没有使用它的经验,因为我的DLL不会抛出异常。

    它也在 GCC documentation 对于x86选项:

    -mthreads

    在上支持线程安全异常处理 Mingw32 '.依赖线程安全异常处理的代码必须编译并将所有代码与 -螺纹 选择权。编译时, -螺纹 定义 -D_MT ;链接时,它在特殊线程帮助器库中链接 -lmingwthrd 它清理每个线程的异常处理数据。

    在编写自己的线程安全异常之前,请尝试这样做。

        2
  •  2
  •   laura    16 年前

    在这里张贴最后的答案,以防有人在未来寻找它。该问题是GCC4.4中的一个关键缺陷:

    http://n2.nabble.com/gcc-4-4-multi-threaded-exception-handling-thread-specifier-not-working-td3440749.html

        3
  •  1
  •   Pavel Minaev    17 年前

    尝试与链接 pthreadGCE2 而不是 pthreadGC2 .

        4
  •  1
  •   Loki Astari    17 年前

    我看不出有什么问题。

    尝试添加catch(…)以查看是否还有其他奇怪的事情发生。
    如果一个异常逸出线程(ie run()),那么pthreads将终止应用程序。但我看不出这是在哪里发生的。

    作为旁注:
    尝试通过常量引用捕获异常。