ايران ويج

نسخه‌ی کامل: سوال در مورد آرایه
شما در حال مشاهده‌ی نسخه‌ی متنی این صفحه می‌باشید. مشاهده‌ی نسخه‌ی کامل با قالب بندی مناسب.
صفحه‌ها: 1 2
نمی شه از تو تابع آزاد کرد
این ارور رو میده
آقا حرفمو پس مي گيرم آزاد نمي شه مگر اينكه برنامه كلا بسته بشه و يا با فري آزادش كني
مگه یه قانون کلی نیست که چیزایی که تو تابع تعریف می شن بعد از
خروج از تابع حافظشون آراد می شه
راستی ارور رو می دونی مال چیه ؟
این نوع حافظه فرق می کنه برای اطلاعات بیشتر باید منتظر جواب اساتید سی باشی در ضمن من visual c++ کار نکردم تا حالا
در پاسخ به سوال اول Iron Fist:
از لحاظ نظري بعضي كامپايلر ها اجازه مي دهند كه شما اندازهء حافظه را به صورت پويا و در زمان اجرا تعيين كنيد كه كار دشواري نيست.
اما اگر منظورتان تعيين ابعاد آرايه (تعداد بعد آن 2 بُعدي 3 بعدي و...) است هيچ كامپايلري اين اجازه را نميدهد اما روشي وجود دارد كه مي توان بدين منظور رسيد:

1- آرايه اي از آرايه ها تعريف كنيد مثلا نميدانيد كه در زمان اجرا به آرايه اي 2 بعدي نياز خواهيد داشت يا يك بعدي يا 10 بعدي پس در زمان اجرا هنگامي كه اين مسئله معلوم شد مي توانيد به تعداد اندازهء بعد اول آرايه اگر به بعد آخر نرسيده باشيم (مثلا اگر يك بعدي قرار است با شد و ما بعد اول را تعيين ميكنيم به بعد آخر رسيديم ادامهء متن را بخوانيد كه چه كار كنيم.) اعضائ اين ارايه را از نوع اشاره گري به آرايه اي از اين نوع تعريف ميكنيم و به هر عضو آن آرايه اي از اين نوع به طول بعد دوم و الي آخر تخصيص مي دهيم تا به بعد آخر برسيم در اين جا به هر اشاره گر (كه اعضاء آخرين بعد آرايهء قبل هستند) آرايه اي از جنس سلول هاي مورد نظر به طول بعد آخر نسبت مي دهيم مثلا اگر قرار است كل  آرايه [9, 8, 6, 6, 3] باشد و اعداد صحيح را ذخيره كند اين آرايه آخري را 9 تايي و از جنس عدد صحيح تعريف مي كنيم(نه اشاره گري به عدد صحيح يا اشاره گري به آرايهء عدد صحيح) و سلام البته كمي پيچيده شد ولي خوب!
حالا مسئلهء مهم در اين جا آزاد سازي حافظه است توجه كنيد كه اين كار بايد از آخر به اول انجام گيرد(مي توانيد براي سادگي از يك الگوريتم بازگشتي استفاده كنيد).

----------------------------------------------------------------------------------
در پاسخ به سوال دوم Iron Fist:

اولا بسته به محيط برنامه نويسي پاسخ شما متفاوت است
بايد گفت 2 نوع كلي تخصيص حافظه وجود دارد:

1- تخصيص حافظهء اتوماتيك (مبتني بر Stack يا متغيير هاي عمومي كه از Data Segment استفاده مي كنند).
متغيير هاي محلي كه اسكالر باشند و كلاسهاي غير ديناميك ++C و Structهاي #C همگي از Stack حافظه مي گيرند كه تخصيص و آزاد سازي آن كاملاً به عهدهء كاميپايلر است مگر موردي كه مستقيما از Assembly استفاده شود كه مسئوليت Pop كردن پوشته به عهدهء شماست.

2- در مورد متغيير ها و اشيائي كه از حافظهء ديناميك استفاده مي كنند
ولا بسته به محيط برنامه نويسي پاسخ شما متفاوت است.
در dotNet و JAVA اين كارها توسط GC انجام ميگيرد و غصه نداره.
در Delphi در مورد اشيا كه همگي پويا هستند (يعني از حافظهء ديناميك استفاده مي كنند) تنها در صورتي نياز به Free كردن نيست كه شئ ما ولد شئ ديگري باشد كه والدش پاك سازي حافظه را انجام مي دهد يا اينكه شئ ما از فرزندان IUnknown باشد كه مراجع شمرده شده دارد و به محض صفر شدن مراجع آزاد يازي حافظه صورت ميگيرد.
در مورد ++C هم وضعيت تقريباً شبيه به دلفي است.

حالا اگر به اشاره گرتان آدرس يك متغيير يا شئ اتوماتيك راداشته باشد همه چيز خود به خود لنجام خواهد شد مسئوليت آزاد سازي آن متغيير با كامپايلر است.
اما اگر متغيير يا شئ شما ديناميك است (يعني از حافظهء ديناميك فضا گرفته و اندازهء آن در زمان اجرا تعيين ميشود) و اين شئ طبق آنچه كه گفته شد به طور خود كار پاك سازي نمي شود حتما بايد آنرا آزاد كرد و گرنه نوعي خطا به نام Memory Leaking ايجاد مي شود كه به سختي قابل پيگيري است و در بعضي موارد تا راهندازي مجدد كامپيوتر آن حافظه قابل استفاده نخواهد بود (كه فاجعه است).

با تشكر از توجه شما سعيد.ت اميدوارم مفيد بوده باشد خلاصه اين جوري هاست. اگر مفید بود یک ندا بدید!Cool
از توضیحات شما متشکرم
ولی چیز زیادی نفهمیدم Biggrin
خسرو جان سلام

ساده بگم ، حافظه ای که در یک تابع بصورت دینامیک از حافظه گرفته شده باشه دارای کلاس حافظه Auto نیست . متغیر کلاس حافظه Auto همون متغیر های local هستند که در خاتمه کار تابع نابود میشن ! متغیری که بشکل داینامیک از حافظه گرفته شده باشه به محض خروج از یک تابع به هیچ وجه clean-up نمیشه و باقی میمونه !
علتش اینه که کامپایلر حافظه داینامیک مورد نیاز خودش رو از free store یا Heap تامین میکنه و کنترل این حافظه بر عهده stack frame یا پشته موجود تابع نیست .
یکی از بزرگترین مزیت های اونم در هنگام استفاده از توابعی هستش که یک pointer یا اشاره گر رو برمی گردونن . خب ما چطور میتونیم یک آدرس (اشاره گر) رو از یک تابع رو برگردونیم وقتی که متغیر ما در هنگام به پایان رسیدن کار تابع از بین میره ؟؟؟؟ یعنی ما میخوایم آدرس یه متغیری رو برگردونیم که بعد از پایان کار تابع مفهومی نداره !!
پس حتما باید راه حلی باشه که بتونیم یک اشاره گر معتبر یا Valid رو از چنین تابعی برگردونیم  . بهترین روش همون استفاده از حافظه داینامیک یا Dynamic memory Allocation هست . در پایین واستون مثالی از یک تابع رو زدم که یک اشاره گر یا pointer برمیگردونه :

1-مثالی از یک تابع که کاملا اشتباه عمل می کنه ( باز گردوندن آدرس متغیری با کلاس حافظه Auto ) متغیر ما بعد از خاتمه کار تابع معتبر نیست و تابع ما آدرسی رو برمیگردونه که هیچ مفهومی نداره !!


کد:
int* myfunc ( int data )
{
    double result=0;
    result+=data;

    return &result;

}


2-مثالی برای استفاده از Dynamic memory allocation  در توابع . ساخت متغیری که بعد از خاتمه کار تابع هنوز معتبره و ما آدرس اونو به تابع برمیگردونیم !

کد:
int* myfunc ( int data )
{
    double* result = new int(0);
    *(result)+=data;

    return result;

}

متغیر result در مثال اول یک متغیر local با کلاس حافظه Auto هست و آدرس اون بعد از اتمام تابع بی مفهوم میشه پس کد ما نباید آدرس اونو برگردونه ! بهترین راه حل جایگزین در مثال 2 ارائه شد که از حافظه داینامیک استفاده می کنه و مشکل رو برطرف می کنه !

نکته ای هم به دوست عزیزمون آقای سعید ( Programmer ) : بسیار خوشحالم فرد با سواد و با معلوماتی مثل شما در این سایت حضور داره . امیدوارم که خود بنده بتونم از تحربیات شما استفاده کاملی بکنم چون تجربه ناچیزی در زبان ++C دارم . فقط درخواستی دارم از شما و اونهم اینه که در پاسخ به دوستان کمترین اشاره رو به مسایل حاشیه ای بکنید و سعی کنید در ساده ترین حالت ممکن و اگر شد با گذاشتن مثال دوستان رو راهنمایی بکنید . به عنوان مثال مسایلی مثل نحوه کارکرد بازگشتی Stack frame یا نحوه اختصاص حافظه در Data segment  که بیشتر به مباحث سطح پایین و طراحی کامپایلرها برمیگرده و یا نحوه کارکرد Garbage cleaner ها و فریم ورک زبانهای دیگه مثل #C یا جاوا که ساختاری کاملا متفاوت دارند و حتی Memory leakage ، برای افراد مبتدی تا حدود زیادی قابل فهم نیست . بیان ساده تر کار فهم رو آسون تر میکنه . خیلی متشکر از توجه شما .

با آرزوی موفقیت برای دوستان



ممد جان از توضیحاتت ممنونم
خیلی جالب بود
تازه فرق این دوتا رو فهمیدم Biggrin

با تشکر خسرو
متشکرم استاد
من هم چیزای جدیدی یاد گرفتم
همین حرفا رو از استادم پرسیدم جواب بی ربط به هم داد
خوشحالم که جواب من برای شما مفید بوده !
سلام
تا اونجایی که من میدونم:
در C++ خیلی خیلی ساده تر از C است
شما فقط یه اشارهگر تعریف میکنی بعد:
esmeesharegar = new noe dade[toole araye];x
توی C هم که دوستان توضیح دادند که شما باید از تابع زیر استفاده کنی:
malloc
البته توابع کاربردی دیگه ای هم هستن که اگه خواستی بگو تا بنویسم
bye
صفحه‌ها: 1 2