PDA

View Full Version : سوال: آیا این روش برای نمایش فرم ها صحیح است ؟



مهران رسا
سه شنبه 19 مرداد 1389, 17:00 عصر
سلام؛

آیا روش زیر برای نمایش فرم صحیح است ؟

var
Frm: TForm2;
begin
Frm := TForm2.Create(self);
try
Frm.ShowModal;
finally
Frm.Free;
end;

با استفاده از این روش برخی اوقات خطای Invalid Pointer Operation دریافت میکنم .

vcldeveloper
سه شنبه 19 مرداد 1389, 18:18 عصر
با استفاده از این روش برخی اوقات خطای Invalid Pointer Operation دریافت میکنم .
فرمی که به اون شکل میسازید و آزاد می کنید، بهتره که پارامتر Create اش nil باشه. البته در این کد شما، اصلا معلوم نیست Self به چی اشاره میکنه. فرم ها Owner شون یا Application هست، یا nil. خیلی کم پیش میاد که لازم باشه یک شی دیگه رو به عنوان owner فرم تعیین کنید.

tdkhakpur
سه شنبه 19 مرداد 1389, 18:23 عصر
در حالت فوق شما فرم را با استفاده از پارامترهای فرم اصلی می سازید که ممکن هست در این حالت ممکن هست قسمتی از داده های فرم قبلی آزاد شده باشد به همین دلیل گاهی از اوقات بطور تصادفی در برنامه ایراد گرفته میشه بهترین حالت ایجاد فرم با استفاده از پارامترهای برنامه اصلی هست


var
Frm: TForm1;
begin
Frm := TForm1.Create(Application);
try
Frm.ShowModal;
finally
Frm.Free;
end;
end;

vcldeveloper
سه شنبه 19 مرداد 1389, 19:42 عصر
بهترین حالت ایجاد فرم با استفاده از پارامترهای برنامه اصلی هستاستفاده از Application به عنوان Owner در همچین کدی، ارزش خاصی نداره، و صرفا باعث کاهش performance برنامه میشه. علتش هم اینه که، Owner مسئول آزادسازی فرم ایجاد شده هست، در حالی که در همچین کدی، فرم داره بلافاصله بعد از اتمام کارش آزاد میشه، پس عملا Owner اینجا نقشی نداره. از طرف دیگه، تعیین Owner باعث میشه که متد InsertComponent آون شی Owner فراخوانی بشه، و اون شی تمامی اشیاء متعلق به خودش را از ورود شی جدید به لیست مطلع کنه، و در زمان آزاد شدن اون فرم هم، مجددا همین روال را برای با خبر کردن اشیاء متعلق به خودش از خارج شدن شی از لیست طی کنه. پس به برنامه سربار اضافی تحمیل میکنه.

مهران رسا
پنج شنبه 21 مرداد 1389, 11:17 صبح
آقای کشاورز بازهم پیغام Invalid Pointer Operation ظاهر میشه .

var
Frm: TForm2;
begin
Frm := TForm2.Create(nil);
try
Frm.ShowModal;
finally
Frm.Free;
end;




دقیقاً مشکل از Free شدن بی دلیل یک شی هست . چون وقتی کد رو بدون Frm.Free می نویسم دیگه خطای Invalid Pointer Operation ظاهر نمیشه . فکر میکنید علت چیه ؟



سوال دیگه اینکه صدا زدن رویداد Click دکمه ها به چه صورت باید باشه ؟

vcldeveloper
جمعه 22 مرداد 1389, 18:38 عصر
آقای کشاورز بازهم پیغام Invalid Pointer Operation ظاهر میشه .
کدی که نوشتید، به خودی خود، منجر به این پیغام خطا نمیشه. مشکل از جای دیگه ایی در کدتان هست؛ یعنی مشکل جای دیگه رخ میده، ولی اینجا صداش در میاد! کدی که برای Form2 در زمان ایجاد شدن و نمایش داده شدنش، یا زمان بسته شدن و Destroy شدنش نوشتید، چی هست؟


سوال دیگه اینکه صدا زدن رویداد Click دکمه ها به چه صورت باید باشه ؟

Button1.Click;

مهران رسا
جمعه 22 مرداد 1389, 20:48 عصر
امکانش هست Invalid Pointer Operation به خاطر فراخوانی ناصحیح رویداد کلیک Button ها رخ بده ؟


کدی که برای Form2 در زمان ایجاد شدن و نمایش داده شدنش، یا زمان بسته شدن و Destroy شدنش نوشتید، چی هست؟
در زمان ایجاد شدن و تخریب شدن فرم چیزی ننوشتم . اما الآن متوجه شدم فقط وقتی که اون متد منحوس فراخوانی میشه در ادامه به صورت تصادفی گاهی اوقات Invalid Pointer Operation ظاهر میشه .

کد کلی برنامه یه چیزی شبیه این هست :


Form1
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
BtnShow: TButton;
procedure BtnShowClick(Sender: TObject);

public
procedure GetData(Str: string);
var
PublicRes: string;
end;

var
Form1: TForm1;

implementation

uses Unit2;
{$R *.dfm}

procedure TForm1.BtnShowClick(Sender: TObject);
Var
Frm: TForm2;
begin
Frm := TForm2.Create(nil);
try
Frm.Caption := 'New Caption';
Frm.ShowModal;
finally
Frm.Free;
end;
end;

procedure TForm1.GetData(Str: string);
begin
PublicRes := 'Hello' + Str;
end;

end.


Form2
در Form2 از Frame هم استفاده میکنم .

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, Unit3, StdCtrls;

type
TForm2 = class(TForm)
Frame1: TFrame3;
Btn: TButton;
procedure BtnClick(Sender: TObject);
end;

var
Form2: TForm2;

implementation

uses Unit1;
{$R *.dfm}

procedure TForm2.BtnClick(Sender: TObject);
begin
Form1.GetData('Data');
Frame1.Edit1.Text := Form1.PublicRes;
Frame1.Button1.Click;
end;

end.


این هم پنجره Call Stack در زمان روی دادن خطا :

http://m8spy.com//PersonalFs/M8SPY_Images/CallStack_1.png

vcldeveloper
شنبه 23 مرداد 1389, 01:23 صبح
این هم پنجره Call Stack در زمان روی دادن خطا
خب، توی Call Stack که مشخصه مشکل از کجا ست: TChunk.Destroy.
کدی که داره در متد Destroy از کلاس TChunk شما اجرا میشه، مشکل رو به وجود میاره، نه ساختن و آزاد کردن یک فرم.

در ضمن، کدی که به این شکل نوشتید، از نظر شی گرایی چندان کد جالبی نیست: Form1 به Form2 دسترسی داره، بعد Form2 در بخش های مختلف خودش به Form1 دسترسی پیدا میکنه، و غیره! سعی کنید مرزبندی اشیاء تون از هم رو حفظ کنید، نه اینکه اشیاء همینطوری دائما به خصوصیات و متدهای همدیگه ارجاع بدند. اگر Form2 در زمان شروع به کارش به داده ایی نیاز داره، اون داده را به صورت یک پارامتر به سازنده اش ارسال کنید، یا اگر نمیخواید سازنده رو تغییر بدید، براش یک Property تعریف کنید، و بعد از ساختن آن، و قبل از نمایش آن، به اون property مقدار بدید.

همچنین، وقتی پارامتری از نوع string به یک متد یا تابع ارسال میکنید، و مقدار این string در داخل آن متد تغییر نمیکنه، پارامتر را به صورت const تعریف کنید، تا کامپایلر کدهای مربوط به چک کردن های غیر لازم را براتون تولید نکنه.

مهران رسا
شنبه 23 مرداد 1389, 09:00 صبح
کدی که داره در متد Destroy از کلاس TChunk شما اجرا میشه، مشکل رو به وجود میاره
این کلاس TChunk رو کی درست کرده ؟ من روحمم از درست شدنش خبر نداره ! بعد مورد دیگه اینکه در پنجره CallStack دوازده خط درج شده . بقیه موارد ربطی به این خطا ندارند ؟

vcldeveloper
شنبه 23 مرداد 1389, 12:14 عصر
این کلاس TChunk رو کی درست کرده ؟ من روحمم از درست شدنش خبر نداره !
مربوط به تصویر PNG ایی هست که در برنامه استفاده کردید.


بعد مورد دیگه اینکه در پنجره CallStack دوازده خط درج شده . بقیه موارد ربطی به این خطا ندارند ؟
نه، یک سری از اونها مربوط به پیغام های رد و بدل شده بین پنجره ها هستند. اون چیزی که به کد شما مربوط میشه، اینه که شما یک گزینه رو از منو کلیک کردید، و اون گزینه منو در کد مربوط به رویداد Click خودش، سعی میکنه یک شی رو (با فراخوانی Free) آزاد کنه، که نهایتا منجر به فراخوانی destructor کلاس TChunk میشه. میشه حدس زد که سعی کردید یک PngImage را آزاد کنید، اما عملیات مربوطه با شکست مواجه شده. یک احتمالش این هست که شی ایی که دارید بهش اشاره می کنید قبلا Free شده، ولی اشاره گرش رو nil نکردید.

در هر حال، این خطا به سایر بخش های کدتون مربوط میشه، و ارتباطی با اون چند خط کدی که برای ایجاد و آزاد سازی فرم نوشتید، نداره.

مهران رسا
شنبه 23 مرداد 1389, 14:30 عصر
آقای کشاورز ما بی خیال این Exception شدیم . احتمالاً Ignore کردنش باعث به وجود آومدن مشکل در برنامه که نمیشه ؟ در صورت مثبت بودن پاسخ ، به این صورت میشه از خطا صرف نظر کرد ؟


var
Frm: TForm1;
begin
try
Frm := TForm1.Create(nil);
try
Frm.ShowModal;
finally
Frm.Free;
end;
except
//Hiss !
end;
end;

vcldeveloper
شنبه 23 مرداد 1389, 18:39 عصر
آقای کشاورز ما بی خیال این Exception شدیم . احتمالاً Ignore کردنش باعث به وجود آومدن مشکل در برنامه که نمیشه ؟ در صورت مثبت بودن پاسخ ، به این صورت میشه از خطا صرف نظر کرد ؟
این کار فوق العاده غلط هست! اینجا نشد، جای دیگه، میتونه یک جایی از برنامه تون رو به گند بکشونه!

یادتون باشه که دیباگ کردن هم بخشی از برنامه نویسی هست.

مصطفی ساتکی
شنبه 23 مرداد 1389, 21:38 عصر
آقای کشاورز ما بی خیال این Exception شدیم . احتمالاً Ignore کردنش باعث به وجود آومدن مشکل در برنامه که نمیشه ؟ در صورت مثبت بودن پاسخ ، به این صورت میشه از خطا صرف نظر کرد ؟
شما در كد هايي كه در پست هاي اوليتون قرار داديد اساس شگرايي رو زير سوال برديد از جمله كارهايي اوليه و اساسي Encapsulation است كه در كد هاي قرار داده شده ديده نميشه .

مهران رسا
شنبه 23 مرداد 1389, 21:42 عصر
شما در كد هايي كه در پست هاي اوليتون قرار داديد اساس شگرايي رو زير سوال برديد از جمله كارهايي اوليه و اساسي Encapsulation است كه در كد هاي قرار داده شده ديده نميشه .
فکر میکنید خطای Invalid Pointer Operation به دلیل زیر سوال بردن شی گرایی رخ داده ؟


یادتون باشه که دیباگ کردن هم بخشی از برنامه نویسی هست.
متاسفانه مشکل من همینجاست ! از کامپوننت های زیادی استفاده کردم اما الآن نمیتونم تشخیص بدم منشا خطا کجاست !

SAASTN
شنبه 23 مرداد 1389, 22:10 عصر
متاسفانه مشکل من همینجاست ! از کامپوننت های زیادی استفاده کردم اما الآن نمیتونم تشخیص بدم منشا خطا کجاست !
توی برنامتون از آرایه های داینامیک یا لیست ها استفاده نکردید؟ من مشکلاتی شبیه به این زیاد داشتم، خطاهایی که بی دلیل و اکثرا توی بخشهای مربوط به ترسیمات همین PNGها اتفاق میافتن. و منشا اکثر این خطاها دسترسیهای غیر مجاز حافظه ای توی یه گوشه ی گم و گور دیگه از کد بوده. مثلا چیزی که زیاد برام اتفاق افتاده این بوده که مثلا توی کار با یه آرایه شمارندم بجای اینکه تا Len-1 بره تا Len رفته بوده یا اندیس عنصری که باید تو آرایه دستکاری می شده از طریق یه محاسبه اشتباه بدست می اومده و مقداری خارج از رنج برمی گردونده که عملا باعث میشه داده های مربوط به بخش های دیگه تخریب بشن. و اینکه اکثرا توی PNGها خودش رو نشون میده فکر کنم فقط از نظر آمار و احتمال باشه، چون این بخشها حجم بیشتری از داده رو به خودشون اختصاص می دن و اگه یه داده اشتباهی توی یه آدرس رندوم بخواد تخریب بشه احتمال بیشتری وجود داره که این داده مربوط به یه کنترل رستر باشه.
اگه مسئله یه همچین چیزی باشه عملا برای دیباگش راهی غیر از کد خونی نداره، باید بخشهای مختلف رو حذف کنی و ببینی کی خطا از بین میره و اون بخش ها رو یه بار دیگه به دقت بخونی، من که واقعا سر اینجور چیزا خیلی حالم گرفته می شه، مشکل یه جا دیگست، یه جا دیگه خطا می ده، دو ساعت باهاش ور میری میبینی یه -1 جا افتاده یا یه پرانتزگذاری اشتباه انجام شده ...

مهران رسا
شنبه 23 مرداد 1389, 22:31 عصر
توی برنامتون از آرایه های داینامیک یا لیست ها استفاده نکردید؟
بلآخره یه چیزهایی داره پیدا میشه . کدها رو تکه تکه کردم و الآن یک Exception جدید در تکه که زیر پیدا شده :


if FrmMain.StrBool = 'TRUE' then
Frame2.C1.Checked := true;
Frame2.LST.Items.Clear;
for j := low(FrmMain.DynamicArray) to high
(FrmMain.DynamicArray) do
begin
MyList := Frame2.LST.Items.Add;
MyList.Caption := FrmMain.DynamicArray[j];
end;


http://up.iranblog.com/Files2/5cef4204b7944722bcbf.png

vcldeveloper
یک شنبه 24 مرداد 1389, 01:19 صبح
فکر میکنید خطای Invalid Pointer Operation به دلیل زیر سوال بردن شی گرایی رخ داده ؟نه؛ ولی وقتی کدها را به صورت "در هم" می نویسید، و هر شی ایی برای خودش داده های شی دیگه رو میخونه، و هیچگونه کپسوله سازی رعایت نمیشه، و به طور کلی به اصول شی گرایی اهمیت نمی دید؛ اون وقت نگهداری اون کدها؛ و خواندن آنها، و رفع اشکالات آنها براتون بسیار سخت تر میشه.


مثلا چیزی که زیاد برام اتفاق افتاده این بوده که مثلا توی کار با یه آرایه شمارندم بجای اینکه تا Len-1 بره تا Len رفته بوده یا اندیس عنصری که باید تو آرایه دستکاری می شده از طریق یه محاسبه اشتباه بدست می اومده و مقداری خارج از رنج برمی گردونده که عملا باعث میشه داده های مربوط به بخش های دیگه تخریب بشن.Range Checking رو در تنظیمات کامپایلر در حالت Debug فعال کنید، تا خودِ کامپایلر در زمان دیباگ اینگونه موارد رو بهتون گوشزد کنه.



متاسفانه مشکل من همینجاست ! از کامپوننت های زیادی استفاده کردم اما الآن نمیتونم تشخیص بدم منشا خطا کجاست ! ReportMemoryLeak رو در سورس برنامه تون True کنید، و ببینید آیا بعد از اجرای برنامه، FastMM اصلا بهتون خطایی مبنی بر وجود Memory Leak میده؟ اگر میده، برای چه نوع داده ایی؟ اگر اون اطلاعات مشکلتون رو برطرف نکرد، می تونید از حالت Full Debug مربوط به FastMM استفاده کنید، یا برید سراغ ابزارهای اختصاصی پروفایلینگ مثل AQTime.

با توجه به Call Stack قبلی، بهتره تمرکزتان بیشتر روی جاهایی باشه که از TPngImage استفاده کردید، یا کامپوننت هایی که به نحوی با تصاویر PNG سر و کار دارند.

دیباگ کردن برنامه هم یک فرآیند مهندسی هست، و باید برای آن با قاعده و روش مشخص اقدام کنید، تا مشکل را پیدا و به درستی رفع کنید.

مهران رسا
یک شنبه 24 مرداد 1389, 10:30 صبح
ReportMemoryLeak رو در سورس برنامه تون True کنید، و ببینید آیا بعد از اجرای برنامه، FastMM اصلا بهتون خطایی مبنی بر وجود Memory Leak میده؟هیچ خطایی .

Range Checking رو در تنظیمات کامپایلر در حالت Debug فعال کنید، تا خودِ کامپایلر در زمان دیباگ اینگونه موارد رو بهتون گوشزد کنه.
من هم Range Checking رو فعال کردم . متاسفانه یه جایی از کدمربوط به آرایه های داینامیک مشکل داشت ! بعد از برطرف کردن مشکل ، چندین بار کد رو در شرایط مختلف بررسی کردم و تا الآن که هنوز Invalid Pointer Operation ظاهر نشده .