小编Mic*_*lev的帖子

Delphi 10.2多线程调试$ C0000005 AV

Delphi 10.2最新版本2004,赢得x64 VCL应用程序.

试图调试我的大型多线程应用程序我在奇怪的地方遇到了很多$ C00000005异常.试图缩小问题的范围使我得到了这个最小的例子:创建一些(在我的情况下10个就足以看到问题)线程,用"use debug .dcus"编译.

在第二个设置断点sleep并多次按F9,直到异常被引​​发.

当它的凸起,汇编代码看起来坏了(看截图).RIP指向正确指令中间的点.

当我为Win32编译相同的测试应用程序时,它只是在几个F9之后挂在调试器中,所以我甚至无法制作错误截图.

更新:

有关原始问题的更多信息使我开始寻找调试器问题:我的生活应用程序(VCL win x64)有时会停止处理错误"导致程序无法正常工作的问题".

每个线程都有异常日志记录系统,因此在失败之后日志是空的,我希望在调试器中运行它会给我一些有用的信息.

没有断点,生活应用程序有时(非常罕见,大约每5小时一次)抛出一个异常导致深入到system.pas(查看最后一个屏幕).在这个屏幕上,最后一个System._USstrClr有nil指针.

当我在System._USstrClr上设置断点并多次点击F9 时,我的图像完全相同,最终会出现nil指针.

我没有说这两个问题有相同的原因,只是想了解发生了什么.

从我看到的这只发生在调试器中.

使用Release版本编译的生活应用程序不会引发exeptions,它只是因为"导致程序无法正常工作的问题"而停止,因为我的用户报告(并且没有任何错误信息的空日志).

TMyThread = class (TThread)
  procedure Execute; override;
end;

var
  frmClientTest: TfrmClientTest;
  ThreadList: TList<TMyThread>;

procedure TfrmClientTest.FormCreate(Sender: TObject);
var
  k: integer;
begin
  ThreadList:=TList<TMyThread>.Create;
  for k:=0 to 10 do ThreadList.Add(TMyThread.Create);
end;

procedure TMyThread.Execute;
begin
  FreeOnTerminate:=false;
  repeat
    sleep(100);
    sleep(200);
  until Terminated;
end;
Run Code Online (Sandbox Code Playgroud)

样品

中央处理器: 中央处理器

=================

真正的app异常:

在此输入图像描述

delphi multithreading

7
推荐指数
0
解决办法
350
查看次数

Delphi XE字节数组索引

我像这样使用简单的循环缓冲区

var
  Values: array [byte] of single;
  ptr: byte;
Run Code Online (Sandbox Code Playgroud)

在这个测试例子中

for ptr:=0 to 10 do Values[Byte(ptr-5)]:=1;
Run Code Online (Sandbox Code Playgroud)

我希望设置为1前5个值和最后5个值,但XE4 compiller产生不正确的代码,它使用32位指针数学来计算数组索引:

for ptr:=0 to 10 do Values[Byte(ptr-5)]:=1;
005B94BB C645FB00         mov byte ptr [ebp-$05],$00
005B94BF 33C0             xor eax,eax
005B94C1 8A45FB           mov al,[ebp-$05]
005B94C4 C78485E0FBFFFF0000803F mov [ebp+eax*4-$0420],$3f800000
005B94CF FE45FB           inc byte ptr [ebp-$05]
005B94D2 807DFB0B         cmp byte ptr [ebp-$05],$0b
005B94D6 75E7             jnz $005b94bf
Run Code Online (Sandbox Code Playgroud)

这是我的错误代码和操作字节索引的正确方法吗?

arrays delphi indexing bytebuffer compiler-bug

6
推荐指数
1
解决办法
643
查看次数

Delphi Indy https 请求与自定义 DNS 解析

示例网址: https: //api.binance.com/api/v1/time

使用 TIdDNSResolver 和 cloudflare dns 我可以获得主机 IP。直接请求的形式

https://205.251.219.20/api/v1/time

不起作用,因为据我了解,服务器期望在网址中看到“api.binance.com”。(即使在浏览器中也不起作用)

使用 synapce 和以下补丁将请求的主机替换为已解析的 IP 我使其正常工作

function THTTPSend.InternalDoConnect(needssl: Boolean): Boolean;
  begin
    Result := False;
    FSock.CloseSocket;
    FSock.Bind(FIPInterface, cAnyPort);
    if FSock.LastError <> 0 then
      Exit;
    If ResolvedIP.IsEmpty
      then FSock.Connect(FTargetHost, FTargetPort)
      else FSock.Connect(ResolvedIP, FTargetPort);   // !!
Run Code Online (Sandbox Code Playgroud)

有没有办法使用 Indy 来做同样的事情?

delphi https

4
推荐指数
1
解决办法
754
查看次数

Delphi:如何将所有类字段重置为零值?

我有一个包含许多数字字段的类,字段数量会随着项目开发而增长,所以无论将来添加多少字段都可以很好地重置所有字段.

 TParams = class
  public
    defined:  boolean;
    FirstValue:             byte; // reset from here
    A0:       single; 
    A1:       single; 
    H1:       TPoint;
       // ...............
    A100:     single; 
    LastValue:             byte; // to here
    procedure Reset;
  end;
Run Code Online (Sandbox Code Playgroud)

想到的唯一想法是插入2个字段:应该重置的块之前和之后,并使用FillMemory:

procedure TParams.Reset;
begin
  FillMemory(@FirstValue, Integer(@LastValue)-Integer(@FirstValue),0);
end;
Run Code Online (Sandbox Code Playgroud)

还有更好的方法吗?(我使用的是Delphi 7)

delphi delphi-7

3
推荐指数
1
解决办法
746
查看次数

FireMonkey:如何在所有表单运行时更改样式簿的样式?

我有 2 个样书加载了自定义样式,并希望它们立即应用于所有表单(在 Windows、Tokyo 10.2.3 上进行测试)。

procedure TForm6.Button1Click(Sender: TObject);
  begin
    StyleBook := StyleBook2;
  end;

  procedure TForm6.Button2Click(Sender: TObject);
  begin
    StyleBook := StyleBook1;
  end;
Run Code Online (Sandbox Code Playgroud)

如果我设置了UseStyleManager=true,则此代码不起作用。如果UseStyleManager=false,它有效,但仅适用于 1 种形式。

delphi styles firemonkey

3
推荐指数
1
解决办法
1711
查看次数

Delphi 10:正确同时运行任务的方法

我正在尝试学习如何使用delphi并行库而不是TThread.我有很多要同时运行的任务.每个任务都是等待某个事件的大部分时间,在等待时,我想将执行转到另一个任务.这是我的示例代码:

type

TObj = class
  pos:     integer;
  Done:    boolean;
  Constructor Create;
  procedure DoWork(Sender: TObject);
end;

var

Objects :   array [0..39] of TObj;
tasks :     array of ITask;

constructor TObj.Create;
begin
  pos:=0;
  DOne:=false;
end;

procedure TObj.DoWork(Sender: TObject);
begin
  repeat
    inc(pos);
    sleep(100);
  until Done;
end;

procedure TForm1.StartClick(Sender: TObject);
var
  i:  integer;
begin
  Setlength (tasks ,Length(Objects));
  for i:=0 to Length(tasks)-1 do begin
    Objects[i]:=TObj.Create; 
    tasks[i] := TTask.Create(Objects[i],Objects[i].DoWork);
    tasks[i].Start;
  end;
  sleep(5000);
  Memo1.Lines.Clear;
  for i:=0 to Length(tasks)-1 do begin
    Objects[i].Done:=true;
    Memo1.Lines.Add(IntToStr(Objects[i].pos));
  end;
end;
Run Code Online (Sandbox Code Playgroud)

我启动N个任务,每个应该在100ms内将其计数器增加1.然后我等待5秒并检查任务的值.我觉得它们至少几乎相等,但真正的Memo1输出显示前12个值约为50,其他4个值约为20-30(我正在运行Ryzen 1600),并且我觉得奇怪的是,所有值都是最小的0!

显然,40个实际上只有16个任务在5秒内完成了至少一次,所以我想知道如何将睡眠(100)替换为实际将执行传递给另一个任务?

delphi multithreading task

1
推荐指数
1
解决办法
1999
查看次数