c++ - 无法捕获 std::invalid_argument

标签 c++ exception error-handling

我遇到了捕获 std::invalid_argument 异常的问题,我无法跟踪。我正在使用 gcc 4.4.0 (windows),pthreads-win32 2.8.0 GC2 dll。

基本上,我尝试从两个线程(主线程和一个使用 pthread_create 开始的线程)大致同时创建类 A 的实例。构造函数抛出一个 std::invalid_argument,但它被应该捕获异常的 try/catch block 包围。然而,这并没有发生(很少,只有一个线程可能会捕获到异常——但是没有关于哪个线程会捕获异常的规则)

如果我尝试仅在其中一个线程上创建对象,则创建会正常工作,并且会捕获到异常。如果我在不同的时间创建这两个对象,则创建会正常工作并捕获异常。如果我尝试同时创建它们,则会调用::terminate()。

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

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)

我看到的输出是:

(Most frequently) $ ./WOpenTest.exe

This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.

This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. terminate called after throwing an instance of 'std::invalid_argument' terminate called recursively

$ ./WOpenTest.exe

This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. M - Invalid!

$ ./WOpenTest.exe

This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. t - Invalid!

This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.

This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. terminate called after throwing an instance of 'std::invalid_argument'
what(): Invalid!

关于我应该做什么和不做什么有什么想法吗?或者我在 pthreads 中遗漏了什么?

最佳答案

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

  • Important if using exception handling: Compile your application with the additional compiler switch "-mthreads". Otherwise exception handling will not work reliable and unspecific crashes may occur. Other problems may arise while propagating exceptions out of a DLL into an application. I have found some hints concerning this in the net, but have no experience with it because my DLL does not throw exceptions.

GCC documentation 中也有描述对于 x86 选项:

-mthreads

Support thread-safe exception handling on 'Mingw32'. Code that relies on thread-safe exception handling must compile and link all code with the -mthreads option. When compiling, -mthreads defines -D_MT; when linking, it links in a special thread helper library -lmingwthrd which cleans up per thread exception handling data.

请在诉诸编写您自己的线程安全异常之前尝试一下。

关于c++ - 无法捕获 std::invalid_argument,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1377833/

相关文章:

python - 捕获 NameError 和错误处理

c++ - 正确排序名称与数字

C++ static const 和初始化(有没有惨败)

c++ - 根据模板函数类型推断变量类型

java - java I/O 中的 NoSuchElement 异常

matlab - Matlab 中的持久性错误对话框

c++ - 无法加载 64 位 dll

php - PHP,如何捕捉零除?

java websocket EOFException发生

angularjs - Angular $ watch空值错误