PDA

View Full Version : سوال: آیا جابجایی تعریف دو آرایه موجب خراب شدن مقدار میشود؟



mbshareat
شنبه 23 فروردین 1404, 12:22 عصر
سلام.احوال؟
یک سوال دارم که اگر بخوام کامل توضیح بدم راحت نیست.
دارم روی متن کار می کنم چیزی مثل تگ HTML دارم که باز و بسته داره(مثلا {a یک a} )
میخوام بررسی کنم که آیا باز و بسته متناوب هستند.یک باز و بعد بسته و بعد باز و...
چند نوع باز و بسته دارم (مثلا a , b , c) پس یک آرایه دارم و برای هر کدوم یک عنصر که تعیین می کنه فرمت آخر یافت شده باز بوده یا بسته
اگر باز بعد از باز بیاد یا بسته بعد از بسته، برنامه در آرایه دیگری یک واحد به تعداد اضافه می کنه و محل رو ثبت می کنه.
اما نمی دونم چرا وقتی میخوام مورد دوم خطای باز و بسته رو ثبت کنم، قبل از مقداردهی با ShowMessage می فهمم مورد اول خراب شده. بازها بررسی کردم هیچ جای دیگه برنامه این ارایه رو مقداردهی نمی کنه اما بعد دو ساعت برررسی، یک کار احمقانه رو امتحان کردم و برنامه درست کار کرد.
ارایه ها رو اینطور تعریف کرده بودم:
E_FB:Array[1..5000] of DWord;
E_FB_No:Word;
FSP:Array[1..11] of StFB;

تبدیل کردم به این و مشکل حل شد!:
FSP:Array[1..11] of StFB;
E_FB:Array[1..5000] of DWord;
E_FB_No:Word;

نمیخوام وارد جزئیات بشم.مثلا اینکه اگر دو باز بعد از هم یافت بشند، محل باز اول رو ثبت می کنم نه دوم و اینکه StFB اینطور تعریف شده:
StFB=Record
St:Byte;
FB:DWord;
End;

یا اینکه FB فایل و بایت است که از ضرب شماره فایل در 65000+بایت به دست میاد.
میخوام بدونم چرا فقط جابجایی محل تعریف آرایه، کد رو درست کرد؟

دلفــي
سه شنبه 26 فروردین 1404, 11:58 صبح
در دلفی، ترتیب اعلان‌های متغیر می‌تواند به‌طور قابل‌توجهی بر رفتار برنامه شما تأثیر بگذارد، به‌ویژه زمانی که با آرایه‌ها و رکوردها سروکار دارید. مشکلی که با آن روبرو شده اید احتمالاً از نحوه تخصیص و دسترسی به حافظه برای آرایه ها و رکوردهای شما ناشی می شود. وقتی آرایه ها و رکوردها را در دلفی تعریف می کنید، به ترتیبی که اعلام می شوند در حافظه تخصیص می یابند. اگر بین این ساختارها وابستگی دارید، تغییر ترتیب آنها می تواند منجر به رفتار غیرمنتظره شود.

mbshareat
چهارشنبه 03 اردیبهشت 1404, 13:55 عصر
ممنونم
پس میشه از زبان برنامه نویسی هم ایراد گرفت؟:لبخندساده:

Mask
سه شنبه 09 اردیبهشت 1404, 13:49 عصر
موضوعی که با آن روبرو هستید به احتمال بسیار زیاد به‌خاطر خطای حافظه (Memory Corruption) است. این‌که جابجایی تعریف متغیرها باعث اصلاح برنامه شده، یک نشانه بسیار واضح از بروز "overrun" یا "overlap" در حافظه است.


دلیل اصلی: ترتیب تعریف متغیرها در حافظه استاتیک
در زبان‌هایی مانند Pascal یا Delphi، ترتیب تعریف متغیرهای global یا static local (مثلاً در بخش var) مشخص می‌کند که این متغیرها در حافظه چگونه پشت‌سر هم قرار بگیرند. یعنی اگر دو آرایه را پشت سر هم تعریف کنید، در حافظه نیز به همان ترتیب قرار می‌گیرند.


مثال:


E_FB: Array[1..5000] of DWord; // فرضاً 20,000 بایت
E_FB_No: Word; // 2 بایت
FSP: Array[1..11] of StFB; // 11 × (1 + 4) = 55 بایت

حالا اگر مثلاً در استفاده از E_FB اشتباهاً به اندیس بزرگ‌تری مثل E_FB[5001] دسترسی پیدا کنید، این دسترسی خارج از محدوده تعریف شده است و داده‌های حافظه بلافاصله بعد از آن (که شامل E_FB_No و سپس FSP) را خراب می‌کند.


وقتی شما جای تعریف FSP و E_FB را عوض کردید، ترتیب فیزیکی آنها در حافظه هم عوض شد. بنابراین اگر خطایی مانند دسترسی بیش از حد به E_FB وجود داشت، دیگر FSP را خراب نمی‌کرد چون ممکن است الان E_FB در انتهای بخش قرار گرفته باشد یا حداقل دیگر FSP در نزدیکی آن نیست.


چطور این مشکل را پیدا کنیم؟
استفاده از رنج چک (Range Check) در کامپایلر.
در Delphi یا Pascal می‌توان {$R+} را فعال کرد.
این گزینه باعث می‌شود که هنگام اجرای برنامه، اگر به عنصری خارج از محدوده آرایه دسترسی پیدا کنید، خطای زمان اجرا دریافت کنید.
بررسی دقیق مقدار اندیس‌ها در زمان اجرای آرایه‌ها. از دستورات مثل Assert یا if برای بررسی رنج استفاده کنید.


توصیه‌ها:
همیشه اندیس‌ها را کنترل کنید.
از Range Check استفاده کنید.
سعی کنید از نوع‌های با اندازه ثابت یا dynamic array (در صورت امکان) استفاده کنید تا حافظه مدیریت‌شده باشد.
در صورت پیچیدگی زیاد، می‌توان از ابزارهای تحلیل حافظه مثل FastMM (برای Delphi) استفاده کرد.

mbshareat
سه شنبه 23 اردیبهشت 1404, 11:59 صبح
سلام علیکم
بر گذشته ها صلوات.
معمولا دلفی اشکال خارج از محدوده بودن رو میگیره. احتمالا در آرایه های کوچکتر از ده عنصری اینطور نیست.
ولی بابت توضیحتون ممنونم.فعلا حوصله بررسی اون برنامه رو ندارم. و لا یسأل عن ذنوبهم المجرمون!:بامزه: