我遇到一个问题,捕获一个我无法追踪的std :: invalid_argument异常。我正在使用gcc 4.4.0(windows),pthreads-win32 2.8.0 GC2 dll。
基本上,从两个线程(主线程和使用pthread_create开始的线程),我尝试在大致相同的时间创建一个A类的实例。构造函数抛出一个std :: invalid_argument,但是它被try / catch块包围,它们应该捕获异常。但是,这种情况不会发生(很少发生,只有一个线程可能会捕获异常 - 尽管没有规则可以做到这一点)
如果我尝试仅在其中一个线程上创建对象,则create将按预期工作,并捕获异常。如果我在不同的时间创建两个对象,则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(){}
makefile是:
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_argument'的实例 终止被称为递归
或
$ ./WOpenTest.exe
此应用程序已请求 运行时以异常方式终止它 办法。请联系申请表 支持团队获取更多信息。 M - 无效!
或
$ ./WOpenTest.exe
此应用程序已请求 运行时以异常方式终止它 办法。请联系申请表 支持团队获取更多信息。 t - 无效!
或
此应用程序已请求 运行时以异常方式终止它 办法。请联系申请表 支持团队获取更多信息。
此应用程序已请求 运行时以异常方式终止它 办法。请联系申请表 支持团队获取更多信息。 投掷后终止调用 'std :: invalid_argument'的实例 what():无效!
关于我应该做什么的任何想法,我不是?或者pthreads我缺少的东西?
答案 0 :(得分:2)
您已得出结论,这与MinGW链接到的单线程库有关。我找到了一个关于configuring NetBeans to use MinGW的页面,它在“使用Posix线程进行多线程处理”部分提供了以下建议:
- 如果使用异常处理,则很重要:使用其他编译器开关“-mthreads”编译应用程序。否则,异常处理将无法正常工作,并且可能会发生非特定的崩溃。将异常从DLL传播到应用程序时可能会出现其他问题。我在网上找到了一些关于此的提示,但没有经验,因为我的DLL不会抛出异常。
在GCC documentation中也为x86选项进行了描述:
-mthreads
支持“
Mingw32
”上的线程安全异常处理。依赖于线程安全异常处理的代码必须使用-mthreads
选项编译和链接所有代码。编译时,-mthreads
定义-D_MT
;链接时,它链接在一个特殊的线程帮助程序库-lmingwthrd
中,它清除每个线程的异常处理数据。
请在尝试编写自己的线程安全例外之前尝试。
答案 1 :(得分:2)
在此处发布最终答案,以防将来有人查找。这个问题是gcc 4.4中的一个关键错误:
答案 2 :(得分:1)
尝试与pthreadGCE2
而不是pthreadGC2
进行关联。
答案 3 :(得分:1)
我看不出任何错误。
尝试添加一个catch(...)以查看是否还有其他奇怪的事情发生 如果异常转义了线程(即run()),则pthreads将终止应用程序。但我看不出发生了什么。
正如旁注:
尝试通过const引用捕获异常。