2009-09-04 86 views
1

我碰到一个醒目的std :: invalid_argument不同的是,我不能追踪的问题。我使用的是gcc 4.4.0(windows),pthreads-win32 2.8.0 GC2 dll。无法赶上的std :: invalid_argument

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

如果我只尝试在其中一个线程上创建对象,则创建按原样工作,并发现异常。如果我在不同的时间创建这两个对象,则该创建将按其应有的方式工作,并捕获异常。如果我尝试同时创建它们,:: 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_argument' 的 实例 终止递归调用

$ ./WOpenTest.exe

此应用程序已请求 运行后叫终止它在一个不寻常的 方式。请联系应用程序的 支持团队以获取更多信息。 M - 无效!

$ ./WOpenTest.exe

此应用程序已请求 运行时终止它在一个不寻常的方式 。请联系应用程序的 支持团队以获取更多信息。 t - 无效!

此应用程序已请求 运行时终止它在一个不寻常的方式 。请联系应用程序的 支持团队以获取更多信息。

此应用程序请求 运行时终止它在一个不寻常的 方式。请联系应用程序的 支持团队以获取更多信息。 终止调用后抛出一个 实例'std :: invalid_argument'
什么():无效!

任何想法,我应该做什么,我不是?或者我错过了pthreads?

+0

我已经找到了答案,把它归结为MinGW的MSVCRT不是线程安全的。 – laura 2009-09-04 10:09:10

回答

2

在这里发布最终答案,以防有人在未来寻找它。问题是在GCC 4.4重大错误:

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

+0

看起来这个链接不再有效。出于好奇,libstdC++如何链接到您的应用程序中?它是静态还是动态完成的? 我遇到了与mingw-gcc4.5.2类似的问题,但前提是我要动态链接到libstdC++ 6.dll – greatwolf 2011-06-02 10:23:12

+0

这是前一阵子。我认为http://mingw-users.1079350.n2.nabble.com/gcc-4-4-multi-threaded-exception-handling-amp-thread-specifier-not-working-td3440749.html是同样的事情,但这只是一个快速的谷歌搜索。 – laura 2011-07-25 15:38:40

1

尝试使用pthreadGCE2而不是pthreadGC2进行链接。

+0

我试过这样做(忘记提及它),它什么也没做。据我所知,两个版本之间的区别是它们如何处理线程退出/取消 - 我不知道它是否会对此测试用例产生影响 – laura 2009-09-04 08:53:37

1

我看不到任何错误。

尝试添加一个catch(...)来查看是否有其他奇怪的事情发生。
如果异常转义线程(即run()),则pthreads将终止应用程序。但我看不到发生了什么。

正如旁注:
尝试通过const引用捕获异常。

+0

它也会逃避catch(...),因为有一个mingw问题 - 抛出异常不是线程安全的。在这种情况下,解决方案似乎在编写我自己的线程安全异常。 – laura 2009-09-04 13:07:43

2

您已经断定这与MinGW链接到的单线程库相关联。我发现了一个网页约configuring NetBeans to use MinGW,它有下以下建议“多线程使用POSIX线程”部分:

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

它在GCC documentation还描述了x86的选项:

-mthreads

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

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

+0

感谢您的回答。我编译并链接了-mthreads:运行时错误仍然出现,虽然不像以前那么频繁。但是,“不经常”不够好,所以现在我必须继续使用线程安全的异常。我想我错过了一些东西,但看了所有的海湾合作委员会的选项后,我无法确定那是什么 – laura 2009-09-07 07:01:54