[请教]Access Violation XXXXXXX adress... ( 积分: 100 )

  • 主题发起人 主题发起人 johnathon
  • 开始时间 开始时间
J

johnathon

Unregistered / Unconfirmed
GUEST, unregistred user!
一个 'Access Violation XXXXXXX adress...' 问题。

问题概要:首先做了一个pro1.exe窗体程序,没有任何问题。之后,想要将其中的WaveDec函数抽离出来,放到一个新的unit里面,方便以后做其他程序是调用,于是有了pro2.exe,和unit wWavelets(具体代码下祥).同时,问题也来了:pro2中的button1(button.click调用了新unit中的waveDec函数)只能运行一次,第二次点击这个button的时候,程序报错,错误类型如题.

我用F5+F9调试了,发现pro2中第二次点击button(第一次运行button完全正常)后,程序运行到:
wWavelets.Wavedec中
--------------------------------------------------------------
GetFilterSet(FltN, FltSet);

App.Re.Clear
//就是这里了,第二次使用的时候到这里报错,而第一次点button运行是可以通过这里的
App.Im.Clear;
--------------------------------------------------------------
说明一下,app是一个自定义类(TSingleArray)的实例对象。
我遇到的Access Violation多数是指针指错了位置,以及操作一个数组最大元素以外的元素。上述情况的确是让我无从下手,请达人指点~

联系方式:qq.56370706
eMail.johnathon1983@tom.com

相关程序代码如下:
1)窗体程序pro1的代码
unit pro1;(带有form的unit)

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Menus,
theTypes, Complexs, FFTs;

type
WaveData = packed record
data: array[0..1023] of Single;
end;

TComplexArray = packed record
Re: TSingleArray
//TSingleArray是一个class
Im: TSingleArray;
end;

TForm1 = class(TForm)
Button1: TButton;
Chart1: TChart;
......
...这里是一些空间和其事件的声明,太多略去一部分...
......
procedure s1Click(Sender: TObject);
private
{ Private declarations }
......
...这里是子函数声明,太多略去一部分不相关的...
......
procedure ExtendMode(var V: TSingleArray
LenExt: Integer
ExtMode: string);

...过程WaveDec就时候面出问题的Procedure...
procedure WaveDec(Data: array of TComplex
Step: Integer
FltN, ExtMode: string;
var App, Det: TComplexArray);
public
{ Public declarations }
end;

const
Pi = 3.1415926;
MaxWaveDec: Integer = 13;

var
Form1: TForm1;
data: array of TComplex;

implementation

{$R *.dfm}

...由于篇幅问题,这里就帖出WaveDec的代码,如果还需要其他代码,再帖出相关内容...
procedure tform1.WaveDec(Data: array of TComplex
Step: Integer
FltN, ExtMode:
string
var App, Det: TComplexArray);
var
i: Integer;
FltSet: Filter;
TempDR, TempDI: array of Single;
begin
try
if Step > 12 then
begin
MessageBox(Handle, 'WaveDec,层数不能大于12!', '警告',
MB_OK + MB_ICONWARNING);
Edit2.SetFocus();
Exit;
end;

GetFilterSet(FltN, FltSet);

App.Re.Clear;
App.Im.Clear;
Det.Re.clear;
Det.Im.Clear;

SetLength(TempDR, Length(Data));
SetLength(TempDI, Length(Data));
for i := Low(TempDR) to High(TempDI) do
begin
TempDR := Data.Re;
TempDI := Data.Im;
end;

App.Re.Assign(TempDR);
App.Im.Assign(TempDI);

for i := 1 to Step do
Dwt(App, Det, FltSet, ExtMode);
except
end;
end;

...这里是使用到WaveDec过程的Button...
procedure TForm1.Button1Click(Sender: TObject);
var
i, Count, Step, ChanalN: Integer;
data: array of TComplex;
CApp, CDet: TComplexArray;
WName, ExtMode: string;
begin
Count := StrToInt(Edit1.Text);
ChanalN := ComboBox1.ItemIndex;
try
SetLength(data, Count*1024);
GetMStream(data, Count, ChanalN);
Step := StrToInt(Edit2.Text);
WName := ComboBox2.Items.Strings[ComboBox2.ItemIndex];
ExtMode := ComboBox3.Items.Strings[ComboBox3.ItemIndex];

CApp.Re := TSingleArray.Create();
CApp.Im := TSingleArray.Create();
CDet.Re := TSingleArray.Create();
CDet.Im := TSingleArray.Create();

WaveDec(data, Step, WName, ExtMode, CApp, CDet);

for i := Low(data) to High(data) do
Series1.AddXY(i, data.Re, '', clTeeColor);
for i := 0 to (CApp.Re.Count-1) do
Series3.AddXY(i, CApp.Re, '', clTeeColor);
for i := 0 to (CDet.Re.Count-1) do
Series4.AddXY(i, CDet.Re, '', clTeeColor);
finally
CApp.Re.Free;
CApp.Im.Free;
CDet.Re.Free;
CDet.Im.Free;
end;
end;

2)由于要制作需要,目的是把WaveDec这个函数从原来的unit(uWaveTest)中抽离出来,也就是函数和原来的窗体单元分离,放入一个新的unit里面.使用时,只要主窗体程序pro2 uses这个unit就可以使用WaveDec函数了。

第二个窗体程序pro2,及其含有WaveDec的 unit的代码如下:
unit pro2;(带有form的unit)

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, TeeProcs, TeEngine, Chart,TeeComma, Series,

wWavelets
//wWavelets就是含有WaveDec的unit;

type
TForm1 = class(TForm)
Panel1: TPanel;
...这里是一些空间和其事件的声明,太多略去一部分...
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
i, Count, Step, ChanalN: Integer;
data: array of TComplex;
CApp, CDet: TComplexArray;
WName, ExtMode: string;
begin
Count := StrToInt(Edit1.Text);
ChanalN := ComboBox1.ItemIndex;
try
SetLength(data, Count*1024);
GetMStream(data, Count, ChanalN);
Step := StrToInt(Edit2.Text);
WName := ComboBox2.Items.Strings[ComboBox2.ItemIndex];
ExtMode := ComboBox3.Items.Strings[ComboBox3.ItemIndex];

CApp.Re := TSingleArray.Create();
CApp.Im := TSingleArray.Create();
CDet.Re := TSingleArray.Create();
CDet.Im := TSingleArray.Create();

WaveDec(data, Step, WName, ExtMode, CApp, CDet);

for i := Low(data) to High(data) do
Series1.AddXY(i, data.Re, '', clTeeColor);
for i := 0 to (CApp.Re.Count-1) do
Series3.AddXY(i, CApp.Re, '', clTeeColor);
for i := 0 to (CDet.Re.Count-1) do
Series4.AddXY(i, CDet.Re, '', clTeeColor);
finally
CApp.Re.Free;
CApp.Im.Free;
CDet.Re.Free;
CDet.Im.Free;
end;
end;

--------下面是含有WaveDec的unit,wWavelets,基本上直接从pro1上copy的----------
unit wWavelets;

interface

uses
wFilterSet,
Dialogs, SysUtils, Windows;

type
WaveData = packed record
data: array[0..1023] of Single;
end;

TComplex = packed record
Re: TFloat;
Im: TFloat

end;

TComplexArray = packed record
Re: TSingleArray;
Im: TSingleArray;
end;

const
Pi = 3.1415926;
MaxWaveDec: Integer = 13;

var
data: array of TComplex;

...这里是子函数声明,太多略去一部分不相关的...
procedure Dwt(var App, Det: TComplexArray
const FltSet: Filter;
ExtMode: string);

...这里就是分离出来的WaveDec过程的声明...
procedure WaveDec(Data: array of TComplex
Step: Integer
FltN, ExtMode: string;
var App, Det: TComplexArray);
implementation

procedure WaveDec(Data: array of TComplex
Step: Integer
FltN, ExtMode:
string
var App, Det: TComplexArray);
var //App,Det长度是由Step决定,而不需要在函数外设定长度
i: Integer;
FltSet: Filter;
TempDR, TempDI: array of Single;
begin
try
if Step > 12 then
begin
MessageBox(Handle, 'WaveDec,分解层数不能大于12!', '警告',
MB_OK + MB_ICONWARNING);

ShowMessage('警告:WaveDec,分解层数不能大于12!');
Exit;
end;

GetFilterSet(FltN, FltSet);

App.Re.Clear
//就是这里了,第二次使用的时候到这里报错,而第一次点button运行是可以通过这里的
App.Im.Clear;
Det.Re.clear;
Det.Im.Clear;

SetLength(TempDR, Length(Data));
SetLength(TempDI, Length(Data));
for i := Low(TempDR) to High(TempDI) do
begin
TempDR := Data.Re;
TempDI := Data.Im;
end;

App.Re.Assign(TempDR);
App.Im.Assign(TempDI);

for i := 1 to Step do
Dwt(App, Det, FltSet, ExtMode);
except
on E: Exception do
ShowMessage('WaveDec产生错误,原因:' + E.Message);
end;
end;
 
设置断点,检查App是否已经变成野指针。
你的代码中没有显式的创建和释放App对象——你应该对App(及其内部对象)的生灭进行
断点监控。
 
是的,我也知道创建和释放App对象是一个关键点.

但是,问题在于App所在的procedure WaveDec:
procedure WaveDec(Data: array of TComplex
Step: Integer
FltN, ExtMode:
string
var App, Det: TComplexArray);中App定为var,App作为形参,在调用
WaveDec之前已经创建了(buttonclick过程中创建,用完以后也free掉了),实际上App的地址
指向的就是Capp这个对象,如果在WaveDec中就将App.free了,那么CApp怎么得到改变后的数值?

我贴的代码太多但是大体应该是这样一个结构:
unit pro2;
......
procedure tform1.button1click(sender: object);
var CApp, CDet: TComplexArray;
begin
try
Capp, Cdet := Tcomplexarray.Create();
WaveDec(data, Step, FltN, ExtMode, Capp, CDet);
finally
Capp, Cdet.free;
end;
end;

unit wWavelets;
......
Procedure WaveDec(Data: array of TComplex
Step: Integer
FltN, ExtMode:
string
var App, Det: TComplexArray);
var //这里我并没有重新创建App,Det(也不应该创建吧?)
begin
......
App.clear;//清除App,实际上指针地址就是指向的是Capp(调用这个过程时)
//问题也在这里,第二次使用到这里的时候,就变成了'野指针了'
//第一次使用这个函数的时候没有任何问题。
//大家看看,是不是有不该释放的释放了,要释放的没有释放
dosomething;
.....
end;

然而,将WaveDec放到窗体的unit pro2中,作为其一个子过程的话就没有问题,正如上面已经帖出的unit pro1;的代码所示!
 
后退
顶部