工作者这大致是这样
bOK := GetQueuedCompletionStatus(hCompletion,dwTrans,DWORD(pPerHandle),POverlapped(pPerIO),WSA_INFINITE);
if (bOK = FALSE) and (pPerIO <> nil) then
...释放资源
if (dwTrans = 0) then
...释放资源
case pPerIO.nOperationType of
OP_RECV:
...接收拼包->解析->调用下面那段回复代码A
OP_SEND:begin
//***释放发送代码申请的内存 貌似这里有问题
FreeMem(pPerIO^.DataBuff.buf, pPerIO^.DataBuff.len);
GlobalFreePtr(pPerIO);
end;
--------------------
回复代码A
//***申请发送缓冲区
pPerIOData := GlobalAllocPtr(GPTR, SizeOf(PER_IO_DATA));
pPerIOData.nOperationType := OP_SEND;
pPerIOData^.DataBuff.buf := AllocMem(YQSHeaderSize + ms.Size);
pPerIOData^.DataBuff.len := InitYQSHeader(pPerIOData^.DataBuff.buf, 2, 1, ms.Size);
...读取数据到缓冲
if WSASend(AConn.Socket, @pPerIOData^.DataBuff, 1, @pPerIOData^.DataBuff.len, 0, @pPerIOData^.ol, nil) = SOCKET_ERROR then
begin
if (WSAGetLastError() <> ERROR_IO_PENDING) then
begin //出错释放资源
if pPerIOData <> nil then
begin
FreeMem(pPerIOData^.DataBuff.buf, pPerIOData^.DataBuff.len);
GlobalFreePtr(pPerIOData);
exit;
end;
end;
end;
测试环境:
50个C
C->S 每秒20字节请求 S->C回复30K数据
以上代码 我在做测试的时候 在只做了接收不然发送时 未出现问题 说明问题不是出在接收上 所以我只列了发送的代码
错误请问是
Free Heap block 1680040 modified at 1680074 after it was freed OutDbStr
也就是说 我在做了释放后 系统访问了我申请的内存
网上查了资料 有人说 第一次的到IOCP的时候 先不要释放 等结束 再发个标志让它释放 不过找不到例子不知道怎么解决
但我不知道错在哪 应该怎么改 高人指点
---------------------------------------------------
另外 我把发送代码改成 不用overlapped 也就是说不经过IOCP 运行了12小时以上 都没提示过这错 但这样又会取不到回复的字节量
//这里的@pPerIOData^.ol ->nil 不经过IOCP
if WSASend(AConn.Socket, @pPerIOData^.DataBuff, 1, @pPerIOData^.DataBuff.len, 0, nil, nil) = SOCKET_ERROR then
begin
if (WSAGetLastError() <> ERROR_IO_PENDING) then
begin //出错释放资源
if pPerIOData <> nil then
begin
FreeMem(pPerIOData^.DataBuff.buf, pPerIOData^.DataBuff.len);
GlobalFreePtr(pPerIOData);
exit;
end;
end;
end;
//下面直接释放资源
FreeMem(pPerIOData^.DataBuff.buf, pPerIOData^.DataBuff.len);
GlobalFreePtr(pPerIOData);
bOK := GetQueuedCompletionStatus(hCompletion,dwTrans,DWORD(pPerHandle),POverlapped(pPerIO),WSA_INFINITE);
if (bOK = FALSE) and (pPerIO <> nil) then
...释放资源
if (dwTrans = 0) then
...释放资源
case pPerIO.nOperationType of
OP_RECV:
...接收拼包->解析->调用下面那段回复代码A
OP_SEND:begin
//***释放发送代码申请的内存 貌似这里有问题
FreeMem(pPerIO^.DataBuff.buf, pPerIO^.DataBuff.len);
GlobalFreePtr(pPerIO);
end;
--------------------
回复代码A
//***申请发送缓冲区
pPerIOData := GlobalAllocPtr(GPTR, SizeOf(PER_IO_DATA));
pPerIOData.nOperationType := OP_SEND;
pPerIOData^.DataBuff.buf := AllocMem(YQSHeaderSize + ms.Size);
pPerIOData^.DataBuff.len := InitYQSHeader(pPerIOData^.DataBuff.buf, 2, 1, ms.Size);
...读取数据到缓冲
if WSASend(AConn.Socket, @pPerIOData^.DataBuff, 1, @pPerIOData^.DataBuff.len, 0, @pPerIOData^.ol, nil) = SOCKET_ERROR then
begin
if (WSAGetLastError() <> ERROR_IO_PENDING) then
begin //出错释放资源
if pPerIOData <> nil then
begin
FreeMem(pPerIOData^.DataBuff.buf, pPerIOData^.DataBuff.len);
GlobalFreePtr(pPerIOData);
exit;
end;
end;
end;
测试环境:
50个C
C->S 每秒20字节请求 S->C回复30K数据
以上代码 我在做测试的时候 在只做了接收不然发送时 未出现问题 说明问题不是出在接收上 所以我只列了发送的代码
错误请问是
Free Heap block 1680040 modified at 1680074 after it was freed OutDbStr
也就是说 我在做了释放后 系统访问了我申请的内存
网上查了资料 有人说 第一次的到IOCP的时候 先不要释放 等结束 再发个标志让它释放 不过找不到例子不知道怎么解决
但我不知道错在哪 应该怎么改 高人指点
---------------------------------------------------
另外 我把发送代码改成 不用overlapped 也就是说不经过IOCP 运行了12小时以上 都没提示过这错 但这样又会取不到回复的字节量
//这里的@pPerIOData^.ol ->nil 不经过IOCP
if WSASend(AConn.Socket, @pPerIOData^.DataBuff, 1, @pPerIOData^.DataBuff.len, 0, nil, nil) = SOCKET_ERROR then
begin
if (WSAGetLastError() <> ERROR_IO_PENDING) then
begin //出错释放资源
if pPerIOData <> nil then
begin
FreeMem(pPerIOData^.DataBuff.buf, pPerIOData^.DataBuff.len);
GlobalFreePtr(pPerIOData);
exit;
end;
end;
end;
//下面直接释放资源
FreeMem(pPerIOData^.DataBuff.buf, pPerIOData^.DataBuff.len);
GlobalFreePtr(pPerIOData);
解决方案 »
- DELPHI程序员现在好招么?
- Delphi FastReport问题
- 有请秀锋大侠jadeluo:还是关于两字符串比较问题
- 问两个问题,请大家帮忙!
- 音量的控制
- 急!!关于sql查询!
- ftp
- 项目大讨论,进者得分!!!
- 在一个改写上下文菜单的DLL在98下注册成功但无效,是DLL的原因,还是系统的原因?
- 怎么清空收藏夹和临时文件夹,给出源代码?
- 各位帮帮忙;我在treeview中遍历的是文件夹和文件,怎样做能在treeview的节点上右击遍历文件夹或文件弹出快捷菜单(菜单中的内容有新建一级节点,二级节点,三级节点,四级节点,删除节点(其中1,2,3级节点是文件,4级节是txt文档)。
- 如何用delphi输入数学公式,如开根号,积分等符号呢?
需要使用的时候调用Attach增加引用计数(如果返回的是Nil表示对象已经处于释放状态),成功之后调用Free释放引用计数,由于第一次创建的时候会自动增加一个引用计数,那么对于创建者就可以在需要的时候Free,这样子并不影响其它线程的使用,只要记得Attach(包括Create)和Free相对应即可(注:Delphi2007以下版本请把{$Region}和{$EndRegion}删除)
unit UnitManagedObject;interfaceuses
Windows
;
type
TManagedObject = class(TObject)
{Management Properties}
{$region}
strict private
FManagementCount : Integer; //对象引用计数
{$endRegion}
public
{structor}
{$region}
constructor Create;
{$endregion}
public
{Management}
{$region}
procedure Free;
function Attach:TManagedObject;
function Detach: Integer;
{$endRegion}
end;
implementation{TManagedBaseObject}
{$region}
{structor}
{$region}
constructor TManagedObject.Create;
begin
Inherited Create;
FManagementCount := 1;
end;
{$endregion} {Management}
{$region}
function TManagedObject.Attach : TManagedObject;
begin
Result := Nil;
if InterlockedIncrement(FManagementCount) = 1 then
begin
InterlockedDecrement(FManagementCount);
Exit;
end;
Result := self;
end; function TManagedObject.Detach : Integer;
begin
Result := InterlockedDecrement(FManagementCount);
end; procedure TManagedObject.Free;
begin
if Detach>0 then
Exit;
Inherited;
end;
{$EndRegion}{$endRegion}
end.
可能这样讲不明白 就是:
接收用一个 (单IO_Overlapped结构A)
发送能不能也用 (单IO_Overlapped结构A) 来共用? 还是只能为发送重新申请一个空间 来用呢?