- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我被要求为 friend 查看一些代码。 (由于 MFC 和很多糟糕的代码,我犹豫是对的,但他赢了……)
这是一个基于对话框的应用程序,使用了 CAsyncSocket
。
问题表现为一些不间断的调试中断和其他类似的事情——MFC ENSURE()
宏也有问题——检查套接字是否为空。所有问题都发生在 MFC 的深处。
一些谷歌搜索显示如果在 Vista/XP 中使用主题可能会发生资源泄漏,但我认为这不是这里的问题。
根据我几个小时的调试,代码很差,但基本上它在做以下事情:
(建立连接时没有问题-只有没有连接时才会出现这种情况)
CAsyncSocket
对象上)OnConnect()
中,我们收到连接无效/未连接的通知。OnConnect()
不好),那么我们调用 CAsyncSocket::Close()
,然后调用 CAsyncSocket::Create()
(没有参数)然后调用 CAsyncSocket::Connect(server, port)
请注意,对 Connect()
的初始调用没有对 Create()
的调用。
Create()
? (如果我删除它,它就不再崩溃,但是当我重新建立连接时我也不会连接)我修复了代码,以便所有路径都先调用 Create()
,然后调用 Connect()
。
CAsyncSocket::DoCallBack()
中的断言仍然有问题 - 下面代码的最后一行是断言:
void PASCAL CAsyncSocket::DoCallBack(WPARAM wParam, LPARAM lParam)
{
if (wParam == 0 && lParam == 0)
return;
// Has the socket be closed - lookup in dead handle list
CAsyncSocket* pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, TRUE);
// If yes ignore message
if (pSocket != NULL)
return;
pSocket = CAsyncSocket::LookupHandle((SOCKET)wParam, FALSE);
if (pSocket == NULL)
{
// Must be in the middle of an Accept call
pSocket = CAsyncSocket::LookupHandle(INVALID_SOCKET, FALSE);
ENSURE(pSocket != NULL);
如果我逐步执行该操作,则会收到消息框:“遇到不正确的参数”
我认为(但不确定)MFC 正试图在我关闭套接字后回调它。它在回调方法 (DoCallback()
) 中,但我已经在套接字上调用了 Close()
。
所以它看起来确实像 MFC 问题,除非我应该先取消订阅。
最佳答案
真的是你的选择。如果您认为使用另一个套接字实现会更幸运,那就去做吧。
但是,Microsoft 有很多开发人员(我相信其中一些甚至可能是优秀的)。您可能,只是可能,想考虑这样一种可能性,即错误并不全都出在他们的头上。
在我看来,您可以获得的有关他们的 API 和产品的大量帮助也不错。
也许如果您花时间了解 MFC 模型,您会得到那个“顿悟”时刻并更好地理解它。我不是 Winsock 的粉丝 - 我更习惯于 UNIX 世界,其中同步是要走的路,如果你想要异步类型的行为,你只需运行单独的进程/线程。
我怀疑 CAsyncSocket 仍然受到 MFC 是单线程模型(就 GUI 而言)这一事实的阻碍,即使 Windows 已经拥有真正的抢占式线程已经有一段时间了。 [我对那个无能为力的评论可能是错误的,我已经有一段时间没有直接使用 Win32 了]。
更新:
根据您声明自己正在做什么的更新,我相当确定您在创建之前不允许连接。引用 http://msdn.microsoft.com/en-us/library/3d46645f(VS.80).aspx ,
To use a CAsyncSocket object, call its constructor, then call the Create function to create the underlying socket handle ... and for a client socket call the Connect member function.
至于为什么,我认为这增加了额外的复杂性,因为 Windows 需要在事件泵环境中执行异步套接字,因为它们不能阻塞主 GUI 线程。
在 UNIXy 环境中,要么没有事件线程(正常进程),要么网络操作只是手动转移到另一个线程(在 GUI 应用程序中)。
这很可能是很久以前在 WinSock 中做出的设计决定(可能是在 Windows 3.11 中,这是一个对执行异步操作有更多限制的环境)并且一直贯彻 [虽然这是我的推测,UNIX 套接字 API 有从来没有这种消息被泵送的异步行为,它总是倾向于使用 select()
或线程/进程。
进一步更新:
如果您关闭和/或删除了套接字对象,而该套接字对象上有待处理的操作,通常会发生该断言(不是异常)。对于您的情况,我建议它在您关闭它时仍在尝试进行连接。
然后当连接成功或失败时,回调被调用并且它无法在表中找到您的套接字。
这不是 MFC 的问题,是你 friend 的代码违反了约定。如果您执行连接(或任何异步操作),则必须在关闭套接字(或进一步处理它)之前等待成功或失败 - 在这种情况下,这意味着等待调用你的 OnConnect() 函数。
根据内存,您在创建异步套接字时调用了 create()
,然后所有其他事情都会响应到达消息队列的消息(即调用您的 OnXXX( )
函数)。像所有 Win32 GUI 东西一样,消息应该驱动程序(代码运行以响应消息)。这段代码看起来越来越像经典编码,其中程序驱动一切 - 这种方式很疯狂,因为您将让您的程序和异步套接字“线程”争夺控制权。
我已经有一段时间没看过它了,但您应该可以得到一个 CHATSRVR 示例程序,它会告诉您如何操作。
关于c++ - 我的 MFC 套接字代码中的 CAsyncSocket 断言问题和 "improper argument"错误背后的原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/800734/
我有以下实体字段: /** * @Assert\Regex( * pattern = "/^d+\.(jpg|png|gif)$/", * htmlPattern = "/^d+\.(j
我有一个显示查询结果的表。 我使用这个检查表包含结果: cy.get("table", {timeout: 60000}).find("tr[data-index]").should("have.le
void (assert)(int e) { assert(e); } 这里是如何工作的? 最佳答案 void (assert)(int e) 相当于 void assert(int) 为什么
大家好,我的第一次测试遇到了一些问题 我正在写这个 fragment ,但我一直遇到这个问题: java.lang.AssertionError at org.junit.Assert.fail(As
从表中,我获取字符串列表,并想检查当 val!= "A"时,表列表中是否存在字符串“x”: for (int i = 0; i list = new ArrayList(); for(int i=0
我想在现有代码中为 VHDL 断言操作添加一个错误计数器。基本上,我的代码如下所示: assert data = good_data report "Bad data" severity er
我有一个无法处理的问题,所以我想也许你可以帮助我。基本上我有一个函数,它接收 char* 作为参数并对其执行一些操作(我已经检查了这些步骤/函数,它们工作得很好)。如果函数中给出的 char* 是“”
我有一些代码用于检查输入日期是否正确。只需检查是否不超过 12 个月,给定月份中的日期是否正确,并且还应该考虑闰年(因此,基本上是正常的日期检查)。唯一不合适的是年份不应低于 2000。如果日期无效,
我有一个关于 Cypress 断言的问题,最近才开始使用这个测试平台,但是当 URL 返回一个随机数时卡住了,如下所示。 /Geocortex/Essentials/REST/sites/SITE?f
我有一个 Python mock对象,我想断言是否设置了该对象的任何属性。 我不相信PropertyMock将适用于我的目的,因为我必须知道是否设置了任何属性,而不是特定属性。 它也不像我可以模拟模拟
考虑这个简单的基类 Foo 有一个函数 foo 调用一个纯虚函数 foo_,用 Doxygen 记录: class Foo { public: /** \brief This functi
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
我在这段代码中执行 malloc 时遇到问题, /*function starts*/ if(NULL==(partial_results=(bignum_t**)malloc(sizeof
大家好,我想知道如何将整个代码块放入一个断言中? 例如,我有一个数组,我想对数组的每个值进行断言。这是我的代码的样子: for (int value : values) { assert Wi
这不是我的作业——我只是在练习。我似乎无法完全理解这个断言概念。 1) Determine the pre-condition for x that guarantees the post-condi
是否可以在带有时间戳的断言失败时记录信息 例如 int a = 10 assert( a > 100 ); 那么它将失败并像时间戳一样输出 2013-12-02 , 17:00:05 assert f
由于我们公司不使用单元测试,所以我正在自学对自己的代码进行单元测试。我正在使用标准的 .net 测试框架进行一些非常基本的单元测试。 我的一个方法返回一个 IEnumerable我想测试它的输出。所以
我有一个如下所示的对象数组,并且只想针对数组中的某些字段进行断言。 对象数组 - var a = [{"key":"key2","value":"value2","updatedBy":"name1"
我正在尝试编写一个 PSL 断言来检查输入断言的数量是否与输出断言的数量相匹配。 例如: . 在输入上任何时候都可能发生任何事情,输出也可以在任何时候断言。确切时间未知,也不重要。我要验证的是没有信息
我想在Cypress中做一个断言如下: cy.get(a).should('be.visible').or(()=>{ cy.get(b).should('be.visible'); });
我是一名优秀的程序员,十分优秀!