S_OK,S_FALSE,E_FAIL

今天在调试一个ICOP的操作的时候,发现连接被动关闭的时候老是会在一处断言处失败,跟了很久终于发现了问题。在此记录一下:

断言报错的代码如下:

HRESULT CIoCPWorker::UnregIoTask(HRESULT hIokey)
{
	ENTER_CALL("CIoCPWorker_UnregIoTask");
	ASSERT_(SUCCEEDED(hIokey));
	_IoCallback* pIo = reinterpret_cast<_IoCallback*>(hIokey);
	if(pIo->pendingCount._GetCount() == 0)
	{
		TRACE2_L3("--UnregIoTask(), unreg iocp task, fd=%i, io map size=%i\n", 
			pIo->fd, m_ioHandleMap.size() - 1);
		SOCKET temp = pIo->fd;
		m_ioHandleMap.erase(temp);
		return S_OK;
	}
	else
	{
		ASSERT_(pIo->pTask);
		pIo->pTask = NULL;
		TRACE2_L3("--UnregIoTask(), unreg iocp task, fd=%i, io doing=%i\n", 
			pIo->fd, pIo->pendingCount._GetCount());
		return E_FAIL;
	}
}

调用的代码如下:

// 被动关闭/关闭超时
void CTcpPort::EndClose(HRESULT reason)
{
	ENTER_CALL("CTcpPort_EndClose");
	TRACE3_L4("--(%i,%i)EndClose(), reason=%x\n", m_s, m_s2, reason);
	if(m_pPortSink)
	{
		TRACE3_L4("--(%i,%i)EndClose(), report close, reason=%x\n", m_s, m_s2, reason);
		m_pPortSink->OnClose(reason);
		m_pPortSink = NULL;
	}
	if(SUCCEEDED(m_regKey) && reason != S_OK)
	{
		HRESULT hr = m_pIoWorker->UnregIoTask(m_regKey);
		ASSERT_(SUCCEEDED(hr));
		m_regKey = E_FAIL;
		if(m_hClosingTimer)
		{
			m_pThreadsPool->UnregTimer(this,eClosingHandle);
			m_hClosingTimer = NULL;
		}
		Release();
	}
}

运行的时候在 ASSERT_(SUCCEEDED(hr)); 的地方失败。

看了一下S_OK和SUCCEEDED的声明:

#define E_FAIL _HRESULT_TYPEDEF_(0x80004005L)


#define S_OK ((HRESULT)0x00000000L)

#define S_FALSE ((HRESULT)0x00000001L)


#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)

#define FAILED(hr) ((HRESULT)(hr) < 0)

和S_OK放在一起的是S_FALSE,怀疑和这个有关,上网查了一下,果然如此!

S_OK是COM服务器返回正确

S_FALSE是COM服务器返回错误,不过这个错误是可以不处理的,不影响程序正常运行。只是结果不是想要的

E_FAIL是必须处理的错误。

返回E_FAIL,是告诉调用程序--某些地方出错,必须进行处理。否则,程序不能进行下去了。 返回S_FALSE,不是表示出现错误。 而S_OK和S_FALSE,则程序逻辑的不同表示。如果将它们表示成S_1和S_2可能更好理解些! 调用程序只需对返回的S_OK和S_FALSE进行判断,然后决定程序的走向。 最主要的误解是由S_FALSE的名称带来的。  

 所以在使用SUCCEEDED和FAILED来判断返回值的时候,需注意S_FALSE也表示成功,只是其结果并不是想要的,因此FAILED(S_FALSE)返回为"非",SUCCEEDED同理。

当自己写的函数接口返回值为HRESULT的时候,如果想要指明其出错,并且必须被处理时,应返回E_FAIL。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏石奈子的Java之路

原 荐 JVM笔记整理

2103
来自专栏Android干货

浅谈EditText控件的inputType类型

1772
来自专栏大前端_Web

easyUI组件datagrid的二次封装

版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://blog.csdn.net/wkyseo/articl...

2063
来自专栏Java架构师历程

聊聊jvm内存模型及垃圾回收算法

其中New和Tenured属于堆内存,堆内存会从JVM启动参数(-Xmx:3G)指定的内存中分配,Perm不属于堆内存,有虚拟机直接分配,但可以通过-XX:Pe...

1504
来自专栏salesforce零基础学习

salesforce 零基础学习(五十四)常见异常友好消息提示

异常或者error code汇总:https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/...

1857
来自专栏流媒体人生

ATL源码学习4---TearOff接口支持

    http://download.csdn.net/source/1687116

892
来自专栏salesforce零基础学习

salesforce 零基础学习(五十七)Test 类中创建TestUser帮助类

我们写Test Class的时候往往都需要指定一个uesr去run test method。 ? TestUserHelper类如下: 1 public cl...

1847
来自专栏码匠的流水账

频繁产生对象造成gc时间过长案例分析

gc时间过长,平均gc pause的时间要将近4秒,有13%的gc超过10秒,太可怕了,部分gc日志如下:

1561
来自专栏张善友的专栏

Mono 3 的默认Gc是Sgen

Mono 3现在是默认 GC是SGen 垃圾回收器,垃圾回收器几个性能和扩展性方面的改进,以更好地利用多核处理器硬件。SGen 已移植到 Windows 和 M...

27310
来自专栏牛肉圆粉不加葱

JVM GC 那些事(二)- 堆上的内存分配机制

前一篇文章JVM GC 那些事(一)- JVM 运行时内存划分介绍了 JVM 运行时的内存划分情况。本文将介绍 JVM GC “主战场” 堆上的内存分配机制。

611

扫码关注云+社区