当从作为参数传递给新线程的 Functor 的方法中调用时,ConnectNamedPipe() 函数触发 "Debug Error! abort()"
ConnectNamedPipe() function triggers "Debug Error! abort()" when called from within a method of a Functor that's passed as an argument to a new Thread
错误
在 Visual Studio 中执行以下操作会触发“调试错误!已调用 abort()”:
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 ----
// ...
}
}
上下文
以上代码是 PipeFunctor
class 的 connectClient()
方法的一部分,该方法重载了函数调用运算符 ()
;在该重载函数中调用 connectClient()
:
void PipeFunctor::operator()() {
connectClient(); // PipeFunctor::connectClient() called here
// ...
}
connectClient()
方法是通过传递给线程的仿函数间接调用的,即:
PipeFunctor pipeF();
// ...
std::thread (std::ref(pipeF));
假设
当 connectClient()
被 直接 调用时(如下所示),相同的违规 ConnectNamedPipe()
语句执行 而没有 调试 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);
}
PipeFunctor pipeF();
是一个 函数声明 (一个名为 pipeF
的函数不接受任何参数并返回一个 PipeFunctor
)。它不是您可能想要的 变量声明。 PipeFunctor pipeF;
是变量声明,PipeFunctor pipeF{};
.
也是
在任何情况下,当使用 std::thread
时,您都会将 reference 传递给 pipeF
。我的猜测是 pipeF
超出范围并在线程有机会调用其 operator()
之前被销毁。如果 std::thread
回调抛出未捕获的异常(例如通过访问无效 PipeFunctor
对象的数据成员),将调用 std::terminate()
,默认情况下又会调用 std::abort()
。
错误已通过更改行解决:
std::thread (std::ref(pipeF));
至:
std::thread name_of_thread (std::ref(pipeF));
正如@Remy-Lebeau 所提到的,这可能是因为线程“超出范围”从而导致 std::thread 抛出未捕获的异常并随后导致 std::abort() 被调用.
错误
在 Visual Studio 中执行以下操作会触发“调试错误!已调用 abort()”:
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 ----
// ...
}
}
上下文
以上代码是 PipeFunctor
class 的 connectClient()
方法的一部分,该方法重载了函数调用运算符 ()
;在该重载函数中调用 connectClient()
:
void PipeFunctor::operator()() {
connectClient(); // PipeFunctor::connectClient() called here
// ...
}
connectClient()
方法是通过传递给线程的仿函数间接调用的,即:
PipeFunctor pipeF();
// ...
std::thread (std::ref(pipeF));
假设
当 connectClient()
被 直接 调用时(如下所示),相同的违规 ConnectNamedPipe()
语句执行 而没有 调试 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);
}
PipeFunctor pipeF();
是一个 函数声明 (一个名为 pipeF
的函数不接受任何参数并返回一个 PipeFunctor
)。它不是您可能想要的 变量声明。 PipeFunctor pipeF;
是变量声明,PipeFunctor pipeF{};
.
在任何情况下,当使用 std::thread
时,您都会将 reference 传递给 pipeF
。我的猜测是 pipeF
超出范围并在线程有机会调用其 operator()
之前被销毁。如果 std::thread
回调抛出未捕获的异常(例如通过访问无效 PipeFunctor
对象的数据成员),将调用 std::terminate()
,默认情况下又会调用 std::abort()
。
错误已通过更改行解决:
std::thread (std::ref(pipeF));
至:
std::thread name_of_thread (std::ref(pipeF));
正如@Remy-Lebeau 所提到的,这可能是因为线程“超出范围”从而导致 std::thread 抛出未捕获的异常并随后导致 std::abort() 被调用.