紧急求救,程序运行一段时间后会死机.....

时间:2021-05-07 15:21:41
RT...在软件中加了一个麦克风强度捕获显示的模块后,程序在有的机器上运行一段时间后会死机,但是在我的机器上一点问题都没有,以下是这个模块的代码,请各位高手帮忙看下问题有可能出现在哪里....万分感谢!!!!


unit SoundCap;

interface
uses
    Windows, Messages, MMSystem, Classes, SysUtils, Math, Forms,Dialogs, Controls,ExtCtrls;
type
  TData8 = array [0..127] of byte;
  PData8 = ^TData8;
  TData16 = array [0..127] of smallint;
  PData16 = ^TData16;
  
  TSoundCap = Class(TCustomControl)
  private
  protected
  public
    FilterValve : Integer; //音频过滤的阀值
    isCapture : boolean ;
    MaxValue :integer;
    constructor Create(handle : THandle); //overload;
    destructor Destroy; override;
    procedure OpenCapture(handle : THandle);
    procedure CloseCapture;
    procedure OnWaveIn(var Msg: TMessage); message MM_WIM_DATA;   //录音缓冲区满后,进行数据处理,将数据送到播放缓冲区
    procedure StartCap;
    procedure StopCap;
  end;

implementation
var
  WaveIn: hWaveIn;
  hBuf: THandle;
  BufHead: TWaveHdr;
  bufsize: integer;
  Bits16: boolean;
  stop: boolean = false;
  StartTime : DWORD ;
  Count : integer = 0;
  header: TWaveFormatEx;
{ TSoundCap }
//关闭音频捕捉

procedure TSoundCap.CloseCapture;
begin
  if stop = false then
    Exit;
  stop := false;
  while not stop do
  Application.ProcessMessages;
  stop := false;
  WaveInReset(WaveIn);   // 停止声音输入设备工作
  WaveInUnPrepareHeader(WaveIn, addr(BufHead), sizeof(BufHead));
  WaveInClose(WaveIn);   //停止声音输入
  GlobalUnlock(hBuf);
  GlobalFree(hBuf);
end;

constructor TSoundCap.Create(handle: THandle);
begin
  Inherited Create(nil);
  ParentWindow := handle;
  isCapture := false;
  FilterValve := 3;
end;

destructor TSoundCap.Destroy;
begin
  inherited;
  CloseCapture;
end;
//处理Wave数据采集

procedure TSoundCap.OnWaveIn(var Msg: TMessage);  //缓冲区数据已满则处理消息
var
  data8 : PData8;
  i, x, y : integer;
  StartPos, EndPos, SCount : integer;
  tmp : Integer;
begin
  MaxValue := 0;
  Data8 := PData8(PWaveHdr(Msg.lParam)^.lpData);
  for i := 0 to BufSize - 1 do
  Begin
    x := i;
    y := Round(abs(data8^[i] - 128) * 100 / 128); //data8^[i] 为 128 - 256 之间
    tmp := Round(abs(data8^[i] - 128) * 100 / 128);
    if tmp > MaxValue Then
      MaxValue := tmp;
  End;
  if MaxValue = 1 then
    MaxValue := 0;
  Data8 := nil;
  if stop then
    WaveInAddBuffer(WaveIn, PWaveHdr(Msg.lParam),SizeOf(TWaveHdr))
  else
    stop := true;
end;
//打开音频捕捉

procedure TSoundCap.OpenCapture(handle: THandle);
var
  BufLen: word;
  buf: pointer;
begin
  BufSize := 3 * 500 + 100;
  Bits16 := false;
  with header do
  begin
    wFormatTag := WAVE_FORMAT_PCM;
    nChannels := 1;
    nSamplesPerSec :=44100;// 22050;
    wBitsPerSample := integer(Bits16) * 8 + 8;
    nBlockAlign := nChannels * (wBitsPerSample div 8 );
    nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
    cbSize := 0;
  end;
  WaveInOpen(Addr(WaveIn), WAVE_MAPPER, addr(header),self.Handle , 0, CALLBACK_WINDOW);
  BufLen := header.nBlockAlign * BufSize;
  hBuf := GlobalAlloc(GMEM_MOVEABLE and GMEM_SHARE, BufLen); //从全局内存堆中分配一块内存(该内存可移动并且可供应用程序共享),并返回该内存块的句柄
  Buf := GlobalLock(hBuf);                    //锁定全局内存并返回指向该内存块的指针
  with BufHead do
  begin
    lpData := Buf;
    dwBufferLength := BufLen;
    dwFlags := WHDR_BEGINLOOP;
  end;
  WaveInPrepareHeader(WaveIn, Addr(BufHead), sizeof(BufHead)); //预备声音输入缓冲区
  WaveInAddBuffer(WaveIn, addr(BufHead), sizeof(BufHead));     //向声音输入设备发送缓冲区
  stop := true;                                                // 停止声音输入设备工作
  WaveInStart(WaveIn); 
end;
//开始监视捕捉

procedure TSoundCap.StartCap;
begin
  isCapture := true;
  StartTime := GetTickCount;
end;
//停止监视音频捕捉

procedure TSoundCap.StopCap;
begin
  isCapture := false;
end;

end.


欢迎各位内存高手帮忙,.....
 

31 个解决方案

#1


先顶一下,明天睡醒后看看

#2


补充一点,在定时器中调用 MaxValue  这个值,一直在调用

#3


用MemProof检查下有没有内存泄漏

#4


怎么检查?
我看了下任务管理器中,这个程序的内存使用一直在往上涨...要晕了,后面改了下程序
//处理Wave数据采集 

procedure TSoundCap.OnWaveIn(var Msg: TMessage);  //缓冲区数据已满则处理消息 
var 
  data8 : PData8; 
  i, x, y : integer; 
  StartPos, EndPos, SCount : integer; 
  tmp : Integer; 
begin 
  MaxValue := 0; 
  Data8 := PData8(PWaveHdr(Msg.lParam)^.lpData); 
  for i := 0 to BufSize - 1 do 
  Begin 
    x := i; 
    y := Round(abs(data8^[i] - 128) * 100 / 128); //data8^[i] 为 128 - 256 之间 
    tmp := Round(abs(data8^[i] - 128) * 100 / 128); 
    if tmp > MaxValue Then 
      MaxValue := tmp; 
  End; 
  if MaxValue = 1 then 
    MaxValue := 0; 
  Data8 := nil;
  waveInUnprepareHeader(WaveIn, Addr(BufHead), sizeof(BufHead));
  if MaxValue = 1 then
    MaxValue := 0;
  if stop then
  begin
    WaveInPrepareHeader(WaveIn, Addr(BufHead), sizeof(BufHead));
    WaveInAddBuffer(WaveIn, PWaveHdr(Msg.lParam),SizeOf(TWaveHdr));
  end
  else
    stop := true;
end;
 好像效果差不多,只是涨得很慢,上涨的值也不多

#5


MemProof教程,可以定为到内存泄漏的具体代码行
http://blog.csdn.net/hero_yin/archive/2006/09/19/1246569.aspx

简单点就用fastmm4,调试模式下退出会有泄漏提示,但只有泄漏的指针类型,无法定位到代码

#6


检测不到内存泄漏,直接死机了,各位有什么好的办法?

#7


GlobalAlloc主要是为了与16位系统兼容吧
推荐用CreateFileMapping

#8


引用 6 楼 mdejtod 的回复:
检测不到内存泄漏,直接死机了,各位有什么好的办法? 

内存检测的原理是,对所有分配内存的操作计数,new一个就加1,free一个就减1,在程序 退出后看计数器有没有归零,没有则存在泄漏

所以你必须在运行一段时间后 正常退出,才能检测到泄漏....

#9


还有,如果是在"有的机器"上会死机的话,最好重装个最新的声卡驱动,也可能是硬件驱动的问题

#10


CreateFileMapping 不是内存映射么?
哪位帮我看下 ONWAVEIN 函数,问题在这里...

#11


TO :skylkj 
是在配置低一些的机器上就会S机,还有,计数器是在哪里看的?

#12


引用 11 楼 mdejtod 的回复:
TO :skylkj 
是在配置低一些的机器上就会S机,还有,计数器是在哪里看的?

我只是说内存泄漏检测的原理...计数器是memproof自己内置的,它就是通过这个检测是否有泄漏.所以你的程序必须正常退出. 
运行期总不能分配个内存,memproof就报一下吧,它认为你程序退出就应该回收所有资源,所以只有到退出的时候,才去统计是否存在泄漏.你运行期间直接死机,肯定检测不到...

所以你先运行一小会,尽量把各种功能都执行到,然后正常退出程序.memproof就会给出统计结果了. 或者你用aqtime,更强大,但用起来也更复杂

#13


HEAP[SoGuaKK.exe]: 
Invalid Address specified to RtlGetUserInfoHeap( 00060000, 17199300 )

Exception 80000003 BREAKPOINT at 7C921230

那些信息,看不懂,不过在调试信息中出现很多这种情况,程序是不是有问题?

#14


程序上看不出什么问题,
对是对些硬件的操作,是不是API本身有问题.

#15


我也不太清楚了,如果说在函数中一直准备内存,但是现在也有进行释放.可还是死机

#16


帮顶的.....................

#17


高人呢?
大家都很忙??

#18


要疯了,怎么还没高人帮忙?????
顶起来..

#19


这里暂时没高人,就一堆菜鸟而已
看样子似乎是代码越界了

#20


CSDN人才济济,竟然没人帮忙解决问题.....伤心中...

#21


顶起来...
我靠,顶自己的贴还内容太短.....

#22


帮你顶下贴子,关注你的问题。

#23


destructor TSoundCap.Destroy; 
begin 
  inherited; 
  CloseCapture; 
end; 
为什么这么写

 if stop = false then 
    Exit; 
  stop := false; 
  while not stop do 
  Application.ProcessMessages; 
  stop := false; 
这里看起来也有些怪异

#24


谢谢楼上的,以上的代码只在整个应用程序关闭时才会执行....
为了能够响应关闭的按钮事件才这么写的..
还有就是,我用这个单元单独做了个DEMO,怎么跑都不会S机,一集成到软件中就S了

#25


越来越怀疑是你的代码或者内存越界了,如果单独跑没问题的话……
多媒体方面真没接触过,唉……
封装过没有?
最后finally free没?

#26


-_-
看起来像一直在为它准备数据块,好像是越界了
可是我封装成DLL,然后再调用,还是会S机,郁闷得不行了...

#27


我也遇到了同样的问题,期待高人的出现。。。

#28


在网上找了很久。。。最有可能的估计就是内存使用不当引起的。如使用了未初始化的内存、内存溢出了

#29


这样的问题要如何查?因为代码太多,不知道如何下手。请高手指点迷津。。。

#30


我也遇到类似的问题,期待高人解决。

#31


你的程序是频繁的创建内存和释放内存,应该是这样的,造成了没有内存释放

#1


先顶一下,明天睡醒后看看

#2


补充一点,在定时器中调用 MaxValue  这个值,一直在调用

#3


用MemProof检查下有没有内存泄漏

#4


怎么检查?
我看了下任务管理器中,这个程序的内存使用一直在往上涨...要晕了,后面改了下程序
//处理Wave数据采集 

procedure TSoundCap.OnWaveIn(var Msg: TMessage);  //缓冲区数据已满则处理消息 
var 
  data8 : PData8; 
  i, x, y : integer; 
  StartPos, EndPos, SCount : integer; 
  tmp : Integer; 
begin 
  MaxValue := 0; 
  Data8 := PData8(PWaveHdr(Msg.lParam)^.lpData); 
  for i := 0 to BufSize - 1 do 
  Begin 
    x := i; 
    y := Round(abs(data8^[i] - 128) * 100 / 128); //data8^[i] 为 128 - 256 之间 
    tmp := Round(abs(data8^[i] - 128) * 100 / 128); 
    if tmp > MaxValue Then 
      MaxValue := tmp; 
  End; 
  if MaxValue = 1 then 
    MaxValue := 0; 
  Data8 := nil;
  waveInUnprepareHeader(WaveIn, Addr(BufHead), sizeof(BufHead));
  if MaxValue = 1 then
    MaxValue := 0;
  if stop then
  begin
    WaveInPrepareHeader(WaveIn, Addr(BufHead), sizeof(BufHead));
    WaveInAddBuffer(WaveIn, PWaveHdr(Msg.lParam),SizeOf(TWaveHdr));
  end
  else
    stop := true;
end;
 好像效果差不多,只是涨得很慢,上涨的值也不多

#5


MemProof教程,可以定为到内存泄漏的具体代码行
http://blog.csdn.net/hero_yin/archive/2006/09/19/1246569.aspx

简单点就用fastmm4,调试模式下退出会有泄漏提示,但只有泄漏的指针类型,无法定位到代码

#6


检测不到内存泄漏,直接死机了,各位有什么好的办法?

#7


GlobalAlloc主要是为了与16位系统兼容吧
推荐用CreateFileMapping

#8


引用 6 楼 mdejtod 的回复:
检测不到内存泄漏,直接死机了,各位有什么好的办法? 

内存检测的原理是,对所有分配内存的操作计数,new一个就加1,free一个就减1,在程序 退出后看计数器有没有归零,没有则存在泄漏

所以你必须在运行一段时间后 正常退出,才能检测到泄漏....

#9


还有,如果是在"有的机器"上会死机的话,最好重装个最新的声卡驱动,也可能是硬件驱动的问题

#10


CreateFileMapping 不是内存映射么?
哪位帮我看下 ONWAVEIN 函数,问题在这里...

#11


TO :skylkj 
是在配置低一些的机器上就会S机,还有,计数器是在哪里看的?

#12


引用 11 楼 mdejtod 的回复:
TO :skylkj 
是在配置低一些的机器上就会S机,还有,计数器是在哪里看的?

我只是说内存泄漏检测的原理...计数器是memproof自己内置的,它就是通过这个检测是否有泄漏.所以你的程序必须正常退出. 
运行期总不能分配个内存,memproof就报一下吧,它认为你程序退出就应该回收所有资源,所以只有到退出的时候,才去统计是否存在泄漏.你运行期间直接死机,肯定检测不到...

所以你先运行一小会,尽量把各种功能都执行到,然后正常退出程序.memproof就会给出统计结果了. 或者你用aqtime,更强大,但用起来也更复杂

#13


HEAP[SoGuaKK.exe]: 
Invalid Address specified to RtlGetUserInfoHeap( 00060000, 17199300 )

Exception 80000003 BREAKPOINT at 7C921230

那些信息,看不懂,不过在调试信息中出现很多这种情况,程序是不是有问题?

#14


程序上看不出什么问题,
对是对些硬件的操作,是不是API本身有问题.

#15


我也不太清楚了,如果说在函数中一直准备内存,但是现在也有进行释放.可还是死机

#16


帮顶的.....................

#17


高人呢?
大家都很忙??

#18


要疯了,怎么还没高人帮忙?????
顶起来..

#19


这里暂时没高人,就一堆菜鸟而已
看样子似乎是代码越界了

#20


CSDN人才济济,竟然没人帮忙解决问题.....伤心中...

#21


顶起来...
我靠,顶自己的贴还内容太短.....

#22


帮你顶下贴子,关注你的问题。

#23


destructor TSoundCap.Destroy; 
begin 
  inherited; 
  CloseCapture; 
end; 
为什么这么写

 if stop = false then 
    Exit; 
  stop := false; 
  while not stop do 
  Application.ProcessMessages; 
  stop := false; 
这里看起来也有些怪异

#24


谢谢楼上的,以上的代码只在整个应用程序关闭时才会执行....
为了能够响应关闭的按钮事件才这么写的..
还有就是,我用这个单元单独做了个DEMO,怎么跑都不会S机,一集成到软件中就S了

#25


越来越怀疑是你的代码或者内存越界了,如果单独跑没问题的话……
多媒体方面真没接触过,唉……
封装过没有?
最后finally free没?

#26


-_-
看起来像一直在为它准备数据块,好像是越界了
可是我封装成DLL,然后再调用,还是会S机,郁闷得不行了...

#27


我也遇到了同样的问题,期待高人的出现。。。

#28


在网上找了很久。。。最有可能的估计就是内存使用不当引起的。如使用了未初始化的内存、内存溢出了

#29


这样的问题要如何查?因为代码太多,不知道如何下手。请高手指点迷津。。。

#30


我也遇到类似的问题,期待高人解决。

#31


你的程序是频繁的创建内存和释放内存,应该是这样的,造成了没有内存释放