首页 > 解决方案 > ConnectNamedPipe() 函数在从作为参数传递给新线程的 Functor 的方法中调用时触发“调试错误!abort()”

问题描述

错误

在 Visual Studio 中执行以下操作会触发“ Debug Error! abort() has been called ”:

if(m_handle==INVALID_HANDLE_VALUE) return(false); // no return here, therefore m_handle is valid (?)
if(!m_connected){ // some bool indicating a connection doesn't already exist

    if(ConnectNamedPipe(m_handle,NULL)==0){ // --- Abort() message triggered here ----
        // ...
    }
}

语境

上面的代码是重载函数调用运算符connectClient()的类方法的一部分;在该重载函数中调用:PipeFunctor()connectClient()

void PipeFunctor::operator()() {
    connectClient(); // PipeFunctor::connectClient() called here
    // ... 
}

connectClient()方法通过传递给线程的函子间接调用,即:

PipeFunctor pipeF();
// ...
std::thread (std::ref(pipeF)); 

假设

connectClient()直接调用时(如下所示),执行相同的违规语句ConnectNamedPipe()不会出现 Debug abort()错误:

PipeFunctor pipeF();
// ...
pipeF.connectClient();

这使我相信是线程执行语句std::thread (std::ref(pipeF));导致了下游问题。

1.有没有一种方法可以通过传递一个包含并随后调用该ConnectNamedPipe()函数的函子对象来开始一个新线程,而不会产生此调试abort()错误?

2.解决此问题的最佳方法是什么?

所有建议表示赞赏。

谢谢!

附加信息

在调用有问题的函数之前,从(如下所示)方法m_handle中(看似成功地)创建了该变量:connectClient()ConnectNamedPipe()

if(!pipename || *pipename==0) return(false); // no return here. pipeName is a correctly initialized LPTSTR variable

   m_handle = CreateNamedPipe(pipename,PIPE_ACCESS_DUPLEX,
                            PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
                            PIPE_UNLIMITED_INSTANCES,256*1024,256*1024,5000,NULL);

   if(m_handle==INVALID_HANDLE_VALUE){ // produces if(false)
      wprintf(L"Creating pipe '%s' failed\n",pipename);
      return(false);
   }

标签: c++visual-studioc++17named-pipesabort

解决方案


PipeFunctor pipeF();是一个函数声明(一个名为pipeF不带参数并返回 a的函数PipeFunctor)。它不是变量声明,就像您可能想要的那样。PipeFunctor pipeF;是一个变量声明,就像PipeFunctor pipeF{};.

在任何情况下,使用 时std::thread,您都在传递对的引用pipeF。我的猜测是,pipeF在线程有机会调用其operator(). 如果std::thread回调抛出未捕获的异常(例如通过访问无效PipeFunctor对象的数据成员) ,则会std::terminate()被调用,而后者又会std::abort()默认调用。


推荐阅读