ممنون استاد
آها ، یعنی Roslyn ، چیزی شبیه به یک کلاس پایه و پدر و یا شبیه به اینترفیس هاست تا کسانی که میخوان برای سی شارپ کمپایلری بسازن ، از اول ننویسن و از این استفاده کنن؟
چرا هر توضیحی که میدم شبیه یک چیز نامربوط دیگه توصیف می کنید. Roslyn پلتفرم ئه و بصورت سرویس ارائه میشه، شبیه پلتفرم ها و سرویس ها است، شبیه چیز دیگری نیست.
کسانی که میخوان کدی رو کامپایل کنند یا تجزیه و تحلیل کنند یا بهینه کنند و از اینجور موارد ... می توانند از سرویسی که Roslyn ارائه می کنه استفاده کنند.
وگرنه Roslyn نه کیت کامپایلر سازی است و نه سرویس ساختن کامپایلر ئه. سرویسی است برای استفاده از کامپایلر و آنالیز کننده کد و بهینه کننده کد و ...
پس نام کمپایلر زبان سی شارپ چیه؟ یعنی اون کمپایلری که کد سی شارپ را به کد clr ترجمه میکنه ، چیه؟
اسم خاصی نداره، C# Compiler ئه، وقتی
Visual Studio 2002 ارائه شد #C این کامپایلر رو داشت. حالا ممکن بود مایکروسافت در شرکت خودش برای پروژه کامپایلر #C اش یک نام خاصی بکار برده باشه که مشخص نیست، کد های داخل سازمانی همیشه بکار می روند.
مایکروسافت هم نخواسته کامپایلرش رو با اسم خاصی معرفی کنه. اسم پروژه Roslyn هم که اولین بار در سال 2010 مطرح شده ربطی به اسم کامپایلر نداره.
اگر بخواهید به کامپایلری که روی سیستم تون نصب شده اشاره کنید Visual Studio C# Compiler ئه و اگر بخواهید به کامپایلر #C سرویس Roslyn اشاره کنید Roslyn C# Compiler ئه، این کامپایلر ها اسم منحصر بفردی ندارند، کامپایلر سی شارپ هستند، همین.
یعنی پشته یا stack ، فقط زمانی اختصاص پیدا میکنه که یه نخ ای ایجاد شده باشه و پشته برای هر نخ ، حافظه ی مشخصی داره؟ و به چیز دیگه ای ربط نداره؟
بله. نمیدونم منظورتون از ربط چیه.
یعنی پشته ، زمانی که یه متدی را فراخونی میکنیم ، ایجاد نمیشه؟
نه، نمیشه. پشته قبل از فراخوانی متد وجود داشته و ایجادش ربطی به فراخوانی متد ها نداره. اصلا اگر پشته از قبل وجود نداشت، نمیتونست متدی رو فراخوانی کنه. اگر پشته از قبل وجود نداشت نه می توانست به متد پارامتر ارسال کنه و نه می دونست بعد از خاتمه اجرای متد باید به کدوم موقعیت از کد برگرده و نه می توانست وضعیت رجیستر های پردازنده رو به حالت قبل از فراخوانی متد برگردونه.
پس چرا زمانی که کد را در ویژال استودیو trace میکنیم ، وقتی متدی را فراخونی میکنیم ، تا وارد متد یا روریدادی میشه ، در پنجره ی Call Stack ، اسم اون متد و رویداد اضافه و با اتمامش ، از اون لیست حذف میشه؟
چون Debugger برای راحتی شما صرفا بخشی از اطلاعات پشته پردازنده رو نشون میده که مربوط به اون بلوک از کد ئه، وگرنه پردازنده که نمیدونه متد چی هست، پردازنده کل کد ها رو یک سری بایت قاطی هم می بینه و کل داده ها رو یکسری بایت قاطی هم و کل پشته رو یکسری بایت قاطی هم.
حافظه ی پشته برای هر نخ ، چقدره؟
مقدار ثابتی نیست، در هدر فایل اجرایی مشخص میشه و البته در زمان اجرا که آدرس پشته قابل تغییر ئه این اندازه هم قابل تغییر ئه. بصورت پیشفرض در حدود یک یا چند مگابایت ئه.
حافظه ی استک ، توی چه حافظه ای هست؟ از صحبت هاتون بر میاد داخل حافظه ی رجیستر پردازنده باشه و انگار باز هم برمیاد که این حافظه ، مثل داده های معمولی نیست و قابل انتقال به حافظه ی کش و یا حافظه ی فیزیکی رم رو نداشته باشه . درست متوجه شدم؟
خود پشته در حافظه RAM ئه. رجیستر های پردازنده حافظه خیلی کوچکی دارند، اون تو یک سطر متن هم جا نمیشه چه برسه به پشته چند مگابایتی.
در رجیستر های خاص پشته صرفا آدرس سر و ته پشته نگهداری میشه، خود پشته در حافظه RAM قرار داره ولی آدرس شروع و پایانش در رجیستر های پردازنده مشخص شده، یعنی اشاره گر های سر و ته اش در رجیستر ها است.
پس واسه ی همین مقدار مشخص داشتن حافظه ی استک هست که وقتی متدهای زیادی را فراخونی کنیم (در حلقه ای که زیاد باشه . نه صرفا اون حلقه بی نهایت باشه) ، باعث ارور stack overflow میشه؟
بله. دقیقا همینطور ئه.
پس وقتی متد یا رویدادی را فراخونی میکنیم ، باید مقدار جدیدی در حافظه ی استکِ مربوط به نخ خودش ، ثبت کنه . درسته؟
تعداد مقادیر بستگی به سیستم فراخوانی و کامپایلر داره ولی بله، حداقل یک مقدار رو دارن.
حالا رابطه ای بین حافظه ی استک با تعریف متغییر هست؟
بستگی به پلتفرم و کامپایلر و معماری زبان داره، دارید در مورد مطالبی صحبت می کنید که هیچ ربطی به زبان #C نداره، مباحث طراحی کامپایلر ئه.
اینکه حافظه متغیر در چی باشه و نباشه نه ربطی به برنامه نویس #C داره و نه تاثیری روی روال برنامه اش داره و نه جایی مستند شده که در زبان #C متغیر باید در فلان بخش حافظه باشه. کد #C باید کامپایل بشه و اجرا بشه، به هر طریقی که کامپایل و اجرا بشه، شده. اگر در نسخه بعدی کامپایلر تغییری هم رخ بده، نه اتفاقی برای کد #C می افته و نه نتیجه اجرای کد تغییری می کنه. چه اهمیتی داره که متغیر در پشته پردازنده باشه؟ هر چی هست حافظه RAM و تعداد محدودی رجیستر ها است.
استاد ، پس چرا یه کمپایلر دیگه ای علاوه بر این نمیسازه که با C++ Native ، رقابت کنه؟ یعنی اون قابلیت هایی که گفتین را فدا کنه در عوضش سرعت را مثل ++C ، بهبود ببخشه تا هر کس اگه بخاطر مزایای C++ Native بخواد باهاش کد بنویسه (که مهمترینش ، سرعت اجرای کدش هست) ، به رقیب #C اش در اون صورت فکر کنه .
دیگه #C ای که ماشین مجازی و سیستم مدیریت شده ازش حذف بشه که مزیت خاصی نسبت به ++C نداره. میشه یک زبان سطح میانی که نه بدرد برنامه نویسی سریع می خوره و نه بدرد برنامه نویسی سیستمی.
++C خودش به اندازه کافی کتابخانه و کمپوننت و نمونه کد و آموزش و مستندات و متخصص داره، بجز C زبان سطح پایینی نیست که بخواد باهاش رقابت کنه. برنامه نویسی که به ++C و برنامه نویسی سطح پایین مسلط ئه که دلیلی نداره به #C فکر کنه.
برنامه نویسان #C هم که به محیط ساده و کاربر پسند NET. عادت کرده اند براشون برنامه نویسی در محیط C++ Native بخاطر سطح پایین بودن زبان خیلی سخت میشه.
مثل اینکه C++ Native ، یه کمپایلری داره و مایکروسافت برای C++ CLI ، یک کمپایلر دیگه هم درست کرد که کلا 2 کمپایلر کاملا متفاوتی برای ++C هستند .
بله، C++ CLI با مقداری تغییرات زبان ++C رو به زبان های تحت NET. اضافه کرده و کامپایلر و معماریش کلا با C++ Native تفاوت های اساسی زبان های تحت NET. و Native رو داره. از یکطرف محدودیت های NET. رو داره و از طرف دیگه مزایای زبان های Native رو نداره.
نه به اندازه #C راحت و کاربر پسند ئه و نه به اندازه C++ Native سطح پایین و سریع و انعطاف پذیر ئه و نه کاملا با ++C سازگاری داره، یک شتر گاو پلنگ به تمام معنا.