رفتن به مطلب
جامعهٔ برنامه‌نویسان مُدرن ایران

پرچمداران

  1. کامبیز اسدزاده

    کامبیز اسدزاده

    بنیـــان گذار


    • امتیاز

      4

    • تعداد ارسال ها

      379


  2. بهنام صباغی

    بهنام صباغی

    کاربـــر رسمی


    • امتیاز

      2

    • تعداد ارسال ها

      84


  3. قاسم رمضانی منش

    قاسم رمضانی منش

    مدیران مرجع


    • امتیاز

      1

    • تعداد ارسال ها

      93



مطالب محبوب

در حال نمایش مطالب دارای بیشترین امتیاز از زمان چهارشنبه, 18 تیر 1399 در همه بخش ها

  1. 1 امتیاز
    متاسفانه مشکلاتی داره سه بعدی کیوت و دست رو خیلی میبنده من قبلا با یک سریشون برخورد کردم و تصمیم گرفتم برم سراغ VTK خوبم جواب داد دست ادمم باز میذاره توی کار من خیلی وقته سه بعدی کار نکردم و با خود سه بعدی کیوت هم اصلا نساختم همون اوایل محدودیت هایی داشت که فراریمون داد سمت VTK بهتره بقیه دوستان کمک کنند.
  2. 1 امتیاز
    سلام و درود؛ دیتابیس MySQL انتخاب شد، امّا برنامه‌نویس اون قسمت من نبودم.
  3. 1 امتیاز
    اصطلاحاتی که بهتر است در مورد C++ مدرن بدانید! داشتم به این فکر می‌کردم که برخی از مبتدیان برنامه‌نویسی به خصوص کسانی که به سراغ زبان‌هایی مثل سی++ می‌روند معمولاً مستقیم وارد کد نویسی می‌شوند و به این گمان که آغاز برنامه‌نویسی یعنی نوشتن یک کد با خروجی «سلام، دنیا»! دریغ از آن‌ که بعضی از موارد مانند «معرفی کامپایلر و انواع آن» و حتی «ساختار برنامه‌های نوشته شده تحت سی‌پلاس‌پلاس» و یا حتی «مدیریت حافظه» را در نظر بگیرند! من معمولاً در مقالات و آموزش‌های خودم به این اشاره می‌کنم که قبل از هر چیز باید با ساختار برنامه‌های نوشته شدهٔ یک زبان آشنا شد و سپس به بررسی موارد دیگر مانند نحو زبان و یا دیگر ویژگی‌های آن. بنابراین، یکی از خطرناک‌ترین عواملی که موجب خونریزی داخلی یک نرم‌افزار در برنامه‌های نوشته شده توسط برنامه‌نویس درC++ می‌شود عدم مدیریت حافظهٔ اختصاص یافته است که باید بعد از اختصاص یافتن حافظه در زمان معین آن را آزادسازی کند. در صورتی که این کار صورت نگیرد عمل Memory Leak (نَشتِ حافظه) رخ داده است. بسیاری از علاقه‌مندان بر این باورند که چون سی++ دارای GC یا همان Grabbage Collector (زباله‌روب) نیست که البته صحیح است! سی++ دارای GC نیست و این امر محدودیت یا نکته ضعف آن هم نیست! سی++ همه چیز را آزادانه در اختیار برنامه‌نویس قرار می‌دهد تا خود در زمان مناسب روش مدیریت حافظه را انتخاب کند. در علوم رایانه بازیافت حافظه یا زباله‌روبی نوعی مدیریت حافظهٔ خودکار است که عمل مدیریت حافظه‌های اختصاص یافته شده را به دست می‌گیرد و اکثر زبان‌های برنامه‌نویسی مانند #C، جاوا و دیگر موارد مشابه به آن مجهز به این ویژگی هستند که البته وجود چنین ابزار‌هایی می‌تواند توهمی را ایجاد کند مبنی بر آن که دیگر نیازی به مدیریت منابع نیست، اما در بعضی موارد مدیریت منابع هنوز یک الزام است چرا که منابع آزاد شده هنوز هم دلیل بر نشتِ حافظه هستند. این نشت حافظه زمانی اتفاق می‌افتد که اشیاء هنوز قابل دسترس از طرف اشیاءای که زنده هستند اما هرگز مورد استفادهٔ دوباره قرار نمی‌گیرند اتفاق بی‌افتد. در بسیاری از زبان‌های برنامه‌نویسی این ویژگی وجود دارد که طبیعتاً مدیریت توسط GC راه حل بسیار خوب و بی نقصی نیست. اما با توجه به عدم وجود GC در سی++ اکثراً با روش‌های دستی برای مدیریت حافظه می‌پردازند که رایج‌ترین روش آن استفاده از عمل new و delete در اختصاص دادن و آزاد‌سازی حافظه است. بسیاری از ما با سی++ در دانشگاه و یا دروس مرتبط با مفاهیم اولیه برنامه‌نویسی آشنا شده ایم، اما معمولاً مفاهیم مربوطه برای نسل‌های قبلی و منسوخ شدهٔ این زبان است. بهتر است در نظر داشته باشید که برنامه‌نویسی مدرن یعنی پیروی از اصول و قوانین جدیدی که در تکامل یافتن یک زبان به کار گرفته می‌شود. RAII : Resource Acquisition is initialization بنابراین، باید در نظر گرفت مدیریت حافظه از استاندارد ۱۱ به بعد این زبان به روش‌های بسیار مدرن‌تری هوشمند سازی شده است. یکی از بهترین تکنیک‌های موجود در هستهٔ زبان اصطلاح Raiiاست. الگوی RAII مخفف «Resource Acquisition is initialization» که به عنوان یک اصطلاح در برنامه‌نویسی مطرح می‌شود به صورت یک تکنیک (کنترل تخصیص منابع و آزاد‌سازی آن‌ها) یکی از ویژگی‌های اصلی در سی‌پلاس‌پلاس است. با قرار دادن چنین کدی دیگر نیاز به فراخوانی آن کد توسط برنامه‌نویس در مخرب (ویرانگر) نیست و کامپایلر خود این کار را انجام می‌دهد. به طور کلی این الگو هر شیء را مجبور می‌سازد تا در زمان مواجه با رفتار‌های ناهنجار خود را پاکسازی کند. به طور کلی هنگامی که شما یک شیء را مقدار‌دهی اولیه می‌کنید، قبل از انجام آن باید منابع مورد نیاز آن را تأمین کنید (در سازنده). هنگامی که یک شیء از محدوده‌ خارج می‌شود، هر منبعی را که مورد استفاده قرار داده است باید آزاد کند (در مخرب - ویرانگر). نکات کلیدی هرگز نباید یک شیء به حالت نیمه آماده یا نیمه از بین‌ رفته وجود داشته باشد! وقتی که یک شیء ساخته می‌شود، آن شیء باید در حالت آماده باش برای استفاده باشد. وقتی یک شیء از محدوده خارج می‌شود، باید منابع اختصاص یافتهٔ خود را در حافظه آزاد کند (کاربر مجبور به انجام کار دیگری نیست). آیا RAII عنوان بدی برای مفهوم این تکنیک است! از نظر خالق سی‌پلاس‌پلاس نام بهتر می‌تواند به صورت زیر باشد: مدیریت منابع مبتنی بر حوزه (محدوده یا دامنه) : Scope Based Resource Management چیزی که تکنیک RAII را نقض می‌کند چیست؟ اشاره‌گر‌های خام و تخصیص حافظه فراخوانی با کلمهٔ کلیدی new برای دست آوردن یا اختصاص دادن منبع (حافظه). فراخوانی با کلمهٔ کلیدی delete برای آزاد‌سازی منبع (حافظه). اما این مورد به صورت خودکار بعد از خروج از محدوده توسط اشاره‌گر‌ها صورت نمی‌گیرد. void rawPtrFn() { // acquire memory resourceNode* n = newNode; // manually release memory delete n; } بنابراین در صورتی که برنامه‌نویس استفاده از کلمهٔ کلیدی delete را برای آزاد‌سازی حافظه فراموش کند (نشتِ حافظه) رخ می‌دهد. این عمل کافی است تا تکنیک RAII را نقض کنیم. void UseRawPointer() { // Using a raw pointer -- not recommended. Song* pSong = new Song(L"Nothing on You", L"Kambiz Asadzadeh"); // Use pSong... // Don't forget to delete! delete pSong; } بنابراین، راه حل RAII برای این امر در چیست؟ کلاسی داشته باشید که : حافظه را هنگام مقدار‌دهی اولیه تخصیص دهد. حافظه را هنگام فراخوانی مخرب (ویرانگر) آزاد کند. دسترسی به اشاره‌گر‌های زیرین را امکان‌پذیر کند. اشاره‌گر‌های هوشمند (Smart Pointers) یک اشاره‌گر هوشمند یک شیء به سبکِ RAII است که تضمین می‌کند یک اشاره‌گر در هر زمانی که مناسب باشد حافظهٔ اختصاص یافته شده را آزاد می‌کند. به عنوان یک قاعده، برنامه‌های نوشته شده در سی‌پلاس‌پلاس مدرن (پیشرفته) هرگز نباید از اشاره‌گر‌های خام (Raw) برای مدیریت حافظهٔ پویا (مشترک) استفاده کنند. برنابراین، در برنامه‌های مدرن سی++ به ندرت باید از کلمهٔ کلیدی delete جهت آزاد‌سازی حافظه استفاده کرد. در واقع انجام این روش موجب جلوگیری از نشت حافظه است. این ویژگی اساساً مدیریت حافظهٔ خودکار را ارائه می‌دهد. زمانی که یک اشاره‌گر هوشمند دیگر استفاده نمی‌شود (زمانی که از محدودهٔ خود خارج می‌شود) حافظهٔ مورد نظر خود را به طور خودکار آزاد می‌کند.توجه داشته باشید که اشاره‌گر‌های سنتی با عنوان اشاره‌گر‌های خام (Raw Pointer) شناخته می‌شوند. اشاره‌گر‌های هوشمند را می‌تواند یک شکل کلی از GC در نظر گرفت؛ نوعی مدیریت خودکار وقتی که دیگر توسط برنامه مورد استفاده قرار نمی‌گیرند حافظهٔ اختصاص یافتهٔ آن شیء به طور خودکار حذف می‌شود. در استاندارد ۱۱ سی‌پلاس‌پلاس سه نوع اشاره‌گر هوشمند معرفی شده است که همهٔ آن‌ها در فایل سرآیند <memory> از کتابخانهٔ استاندارد STL معرفی شده‌اند. کلاس std::unique_ptr یک اشاره‌گر هوشمند که دارای یک منبع تخصیص حافظهٔ پویا است. این شیء دارای یک اشاره‌گر به حافظهٔ پشته است، بنابراین نمی‌توان آن را کپی کرد. تنها می‌توان آن را جابجا (move) و مبادله کرد. خارج از این بیشتر مانند یک اشاره‌گر عادی رفتار می‌کند. { std::unique_ptr<Person> person(new Person("Kambiz")); if (person != nullptr) person->SetLastName("Asadzadeh"); if (person) DoSomethingWith(*person); } اگر دقت کنید، اپراتور‌های -> و * اطمینان می‌دهد که unique_ptr می‌تواند اکثر اوقات شبیه به یک اشاره‌گر خام (Raw Pointer) استفاده شود. کاربرد‌های معمول از unique_ptr که باعث می‌شود از آن را به یک ابزار واقعی و ضروری تبدیل کند به صورت زیر است: آن‌ها را می‌توان با خیال راحت در داخل یک ظرف (Container) ذخیره کرد. هنگامی که به عنوان متغیر‌های عضو کلاس دیگر استفاده می‌شوند، نیاز به حذف صریح در مخرب را از بین می‌برند. در واقع نیازی نیست در مخرب کلاس خود شیء‌ای را که حافظه‌ای را به خود اختصاص داده است به صورت دستی آزاد کنید. علاوه بر این، موجب جلوگیری تولید خطاهای احتمالی از طرف کپی عضو‌ها برای اشیاء‌ای که باید حافظهٔ پویا داشته باشد در کامپایلر نیز می‌شود. آن‌ها امن‌ترین و توصیه شده‌ترین روش‌هایی برای انتقال مالکیت انحصاری، یا بازگشت به یک unique_ptr از یک تابع که شیء ای را در پشته ساخته است و یا با انتقال یکی از آن‌ها به عنوان آرگومانی که در تابع می‌تواند به عنوان مالکیت بیشتر پذیرفته شود. در هر دو مورد، std::move به طور کلی باید مورد استفاده قرار بگیرد، و این انتقال مالکیت را به صورت صریح بیان می‌کند. انتقال مالکیت از قبل تعیین شده از طرف توابع امضاء شده معلوم می‌شود. از نشت حافطه جلوگیری می‌کند. همچنین، یک شیء unique_ptr می‌تواند حافظهٔ اختصاص داده شده را با استفاده از new[] مدیریت کند: { std::unique_ptr<int[]> array(new int[123]); DoSomethingWith(array.get()); } به طور معمول توصیه می‌شود که برای ساخت یک unique_ptr از std::make_unique() استفاده شود. کلاس std::shared_ptr شامل یک اشاره‌گری است که دارای یک منبع تخصیص حافظهٔ پویا با تفاوت اینکه می‌تواند چندین شیء را به صورت اشتراکی از یک منبع مشترک ردیابی کند. در واقع هنگامی که موجودیت‌های متعددی همان شیء اختصاص یافته شده به حافظه را به اشتراک می‌گذارند، البته این وضعیت همیشه مشهود نبوده و یا ممکن است آن را به یک مالک واحدی اتخصاص دهید. این اشاره گر های هوشمند، شمارنده‌ای از یک رشتهٔ ایمن(thread-safe) برای منبع حافظهٔ مشترک حفظ می‌کند و در زمانی که تعداد مرجع آن به صفر رسید، حذف می‌شود. در واقع این زمانی رخ می‌دهد که آخرین شیء مشترک از آن حذف شود. تابع use_count() نیز تعداد مراجع را بر می‌گرداند. همچنین مشابه unique_ptr این شیء یعنی shared_ptr می‌تواند آرایه‌های پویا را مدیریت کند که این ویژگی از استاندارد ۱۷ به بعد ممکن شده است. چندین شیء از shared_ptr ممکن است دارای همان شیء باشند. اگر یکی از موارد زیر اتفاق بیفتد، شیء از بین رفته و حافظهٔ آن آزاد می‌شود: آخرین بازمانده از شیء shared_ptr از بین رفته باشد. آخرین بازماندهٔ شیٔ shared_ptr که دارای یک اشاره‌گر از طریق اپراتور‌ = و یا reset() است تعیین می‌شود. آنچه که shared_ptr را از unique_ptr متمایز می‌کند آن است که آن‌ها می‌توانند کپی شوند: { auto age = std::make_shared<int>(30); auto aliasAge = age; age.reset(); } کلاسstd::weak_ptr مانند std::shared_ptr است اما با تفاوت آن که شمارندهٔ آن افزایش نمی‌یابد و اختیار شیء را به دست نمی‌گیرد. درواقع، بعضی اوقات نیاز است هنگام ساخت مخازنی از اشیاء‌ای که به اشتراک گذاشته شده‌اند بدانید آن شیء وجود دارد یا خیر. کاربرد آن نیز همراه با shared_ptr معتبر است و اطلاعاتی در بارهٔ اشیائی که توسط shared_ptr به دست گرفته است ارائه می‌کند. چند مثال در بارهٔ اشاره‌گر‌های هوشمند: { std::unique_ptr<int> p(new int); // شیء p قابل استفاده در داخل حوزه است. } // در این بخش که خارج از دامنهٔ اشاره‌گر است حافظهٔ اختصاص یافته آزاد می‌شود. همانطور که مشخص است یک شیء که تحت اشاره‌گر هوشمند مورد استفاده قرار می‌گیرد تا زمانی که خارج از حوزهٔ خود قرار نگیرد قابل استفاده خواهد بود. نمونه کد پایین مثالی از نحوهٔ نمونه سازی تحت اشاره‌گر‌های هوشمند است. void UseSmartPointer() { // Declare a smart pointer on stack and pass it the raw pointer. unique_ptr<Song> song2(new Song(L"Nothing on You", L"Kambiz Asadzadeh")); // Use song2... wstring s = song2->duration_; //... } // song2 is deleted automatically here.
  4. 1 امتیاز

    نگارش 10.1.0

    29 دریافت

    مجموعه کدمترجم‌های گنو یا «کلکسیون کامپایلرهای گنو» (GNU Compiler Collection) که به اختصار GCC نیز خوانده می‌شود، مجموعه‌ای از کامپایلرها برای زبان‌های برنامه‌نویسی مختلف است که بوسیله پروژه گنو بوجود آمده است. جی‌سی‌سی یکی از کلیدی‌ترین اعضای سلسله‌برنامه‌های گنو (به انگلیسی: Gnu ToolChain) است. جی سی سی در ابتدا فقط کامپایلری استاندارد برای سیستم گنو بود ولی امروزه در بسیاری از سیستم‌عامل‌های مشابه یونیکس از آن استفاده می‌شود؛ مانند گنو/لینوکس، خانواده بی‌اس‌دی، اواس ایکس. همچنین جی‌سی‌سی برای معماری‌های سخت‌افزاری مختلف نیز پورت شده است. جی‌سی‌سی در اوایل سرنام کلمات GNU C Compiler بود. زیرا فقط توانایی کامپایل برنامه‌های نوشته شده به زبان C را داشت؛ که با مرور زمان قادر به ترجمه زبان‌های بیشتری مانند سی‌پلاس‌پلاس، فورترن، پاسکال، جاوا، آبجکتیو سی و ایدا شد. پس از آن جی سی سی سرنام کلمات GNU Compiler Collection شد. بنیاد نرم‌افزارهای آزاد جی‌سی‌سی را تحت اجازه‌نامه آزاد گنو (جی‌پی‌ال) نسخه ۳ به انضمام استثناهای منحصر به جی‌سی‌سی منتشر کرده‌است.

    رایگان

  5. 1 امتیاز
    در این مقاله من قصد دارم در رابطه با تفاوت‌های اختصاص دادن حافظه در اِستَک و هیپ توضیحاتی دهم که بسیاری از علاقه‌مندان راجع به آن‌ها سوال کرده‌اند. با توجه به اینکه، از اوایل سیستم‌های کامپیوتری این تمایز در این وجود داشته است که برنامه های اصلی در حافظه فقط خواندنی مانند ROM ، PROM و یا EEPROM نگه داری می‌شوند. به عنوان دیگر از زمانی که سیستم ها پیچیده‌تر شدند برنامه‌ها از حافظه‌های دیگری مانند RAM به جای اجرا در حافظه ROM استفاده کردند. این ایده به خاطر این بود که تعدادی از قسمت های حافظه مربوط به برنامه نباید تغییر یابند و در این حالت باید حفظ شوند. در این میان دو بخش .text و .rodata بخشی‌هایی از برنامه هستند که می‌تواند به بخش های دیگر برای وظایف خاص تقسیم شوند که در ادامه به آن‌ها اشاره شده است. بخش کد، به عنوان یک بخش متنی (.text) و یا به طور ساده به عنوان متن شناخته می‌شود. جایی است که بخشی از یک فایل شیء یا بخش مربوطه از فضای آدرس مجازی برنامه که حاوی دستورالعمل های اجرایی است و به طور کلی فقط خواندنی بوده و اندازه ثابتی دارد می‌باشد. بخش .bss که به عنوانی بخشی ویژه (محل نگه داری اطلاعات تخصیص داده نشده (مقدار دهی نشده)) محلی که متغیر‌های سراسری و ثابت با مقدار صفر شروع می‌شوند. بخش داده (.data) حاوی هر گونه متغیر سراسری و یا استاتیک که دارای یک مقدار از پیش تعریف شده هستند و می‌توانند اصلاح شوند. تصویر زیر طرح معمولی از یک حافظه برنامه ساده کامپیوتری را با متن، داده های مختلف، و بخش‌های استک و هیپ و bss را نشان می‌دهد. برای مثال در کد C به صورت زیر خواهد بود: int val = 3; char string[] = "Hello World"; مقادیر برای این نوع متغیر‌ها در ابتدا در حافظه فقط خواندنی ذخیره می‌شوند. (معمولا در داخل .text) و در زمان اجرای برنامه که به صورت روتین خواهد بود در بخش .data کپی می‌شوند. بخش BSS یا همان .BSS در برنامه‌نویسی کامپیوتر، نام .bss یا bss توسط بسیاری از کامپایلرها و لینکرها برای بخشی از دیتا سِگمنت (Data Segment) استفاده می‌شود که حاوی متغیر های استاتیک اختصاصی که تنها از بیت هایی با ارزش صفر شروع شده است می‌باشد. این بخش به عنوان BSS Section و یا BSS Segment شناخته می‌شود. به طور معمول فقط طول بخش bss نه data در فایل آبجکت ذخیره می‌شود. برای نمونه، یک متغیر به عنوان استاتیک تعریف شده است static int i; این در بخش BSS خواهد بود. حافظه هیپ (Heap) ناحیهٔ هیپ (Heap) به طور رایج در ابتدای بخش‌های .bss و .data قرار گرفته است و به اندازه‌های آدرس بزرگتر قابل رشد است. ناحیهٔ هیپ توسط توابع malloc, calloc, realloc و free مدیریت می‌شود که ممکن است توسط سیستم‌های brk و sbrk جهت تنظیم اندازه مورد استفاده قرار گیرد. ناحیه هیپ توسط تمامی نخ‌ها، کتابخانه‌های مشترک و ماژول‌های بارگذاری شده در یک فرآیند به اشتراک گذاشته می‌شود. به طور کلی حافطه Heap بخشی از حافظه کامپیوتر شما است که به صورت خودکار برای شما مدیریت نمی‌شود، و به صورت محکم و مطمئن توسط پردازنده مرکزی مدیریت نمی‌شود. آن بیشتر به عنوان یک ناحیه شناور بسیار بزرگی از حافظه است. برای اختصاص دادن حافظه در ناحیه هیپ شما باید از توابع malloc(), calloc() که توابعی از C هستند استفاده کنید. یکبار که شما حافظه ای را در ناحیه هیپ اختصاص دهید، جهت آزاد سازی آن باید خود مسئول باشید و با استفاده از تابع free() این کار را به صورت دستی جهت آزاد سازی حافظه اختصاص یافته شده انجام دهید. اگر شما در این کار موفق نباشید، برنامه شما در وضعیت نَشت حافظه (Memory Leak) قرار خواهد گرفت. این بدین معنی است که حافظه اختصاص یافته شده در هیپ هنوز خارح از دسترس قرار گرفته و مورد استفاده قرار نخواهد گرفت. این وضعیت همانند گرفتگی رَگ در بدن انسان است و حافظه نشت شده جهت عملیات در دسترس نخواهد بود. خوشبختانه ابزار‌هایی برای کمک کردن به شما در این زمینه موجود هستند که یکی از آن‌ها Valgrind نام دارد و شما می‌توانید در زمان اشکال زدائی از آن جهت تشخیص نواحی نشت دهنده حافظه استفاده کنید. بر خلاف حافظه اِستک (Stack) حافظه هیپ محدودیتی در اندازه متغیر‌ها ندارد (جدا از محدودیت آشکار فیزیکی در کامپیوتر شما). حافظه هیپ در خواندن کمی کُند تر از نوشتن نسبت به حافظه اِستک است، زیرا جهت دسترسی به آن‌ها در حافظه هیپ باید از اشاره گر استفاده شود. بر خلاف حافظه اِستک، متغیر‌هایی که در حافظه هیپ ساخته می‌شوند توسط هر تابعی در هر بخشی از برنامه شما در دسترس بوده و اساسا متغیر‌های تعریف شده در هیپ در دامنه سراسری قرار دارند. حافظه اِستک (Stack) ناحیهٔ اِستک (Stack) شامل برنامه اِستک، با ساختار LIFO کوتاه‌ شده عبارت Last In First Out (آخرین ورودی از همه زودتر خارج می‌شود) به طور رایج در بالاترین بخش از حافظه قرار می‌گیرد. یک (اشاره گر پشته) در بالاترین قسمت اِستک قرار می‌گیرد. زمانی که تابعی فراخوانی می‌شود این تابع به همراه تمامی متغیرهای محلی خودش در داخل حافظه اِستک قرار می‌گیرد و با فراخوانی یک تابع جدید تابع جاری بر روی تابع قبلی قرار می‌گیرد و کار به همین صورت درباره دیگر توابع ادامه پیدا می‌کند. مزیت استفاده از حافظه اِستک در ذخیره متغیرها است، چرا که حافظه به صورت خودکار برای شما مدیریت می‌شود. شما نیازی برای اختصاص دادن حافظه به صورت دستی ندارید، یا نیازی به آزاد سازی حافظه ندارید. به طور کلی دلیل آن نیز این است که حافظه اِستک به اندازه کافی توسط پردازنده مرکزی بهینه و سازماندهی می‌شود. بنابراین خواندن و نوشتن در حافظه اِستک بسیار سریع است. کلید درک حافظه اِستک در این است که زمانی که تابع خارج می‌شود، تمامی متغیر‌های موجود در آن همراه با آن خارج و به پایان زندگی خود میرسند. بنابراین متغیر‌های موجود در حافظه اِستک به طور طبیعی به صورت محلی هستند. این مرتبط با مفهوم دامنه متغیر‌ها است که قبلا از آن یاد شده است، یا همان متغیر‌های محلی در مقابل متغیر‌های سراسری. یک اشکال رایج در برنامه نویسی C تلاش برای دسترسی به یک متغیر که در حافظه اِستک برای یک تابع درونی ساخته شده است می‌باشد. یعنی از یک مکان در برنامه شما به خارج از تابع (یعنی زمانی که آن تابع خارج شده باشد) رجوع می‌کند. یکی دیگر از ویژگی‌های حافظه اِستک که بهتر است به یاد داشته باشید این است که، محدودیت اندازه (نسبت به نوع سیستم عامل متفاوت) است. این مورد در حافظه هیپ صدق نمی‌کند. خلاصه ای از حافظه اِستک (Stack) حافظه اِستک متناسب با ورود و خروج توابع و متغیر‌های درونی آن‌ها افزایش و کاهش می‌یابد نیازی برای مدیریت دستی حافظه برای شما وجود ندارد، حافظه به طور خودکار برای متغیر‌ها اختصاص و در زمان نیاز به صورت خودکر آزاد می‌شود در اِستک اندازه محدود است متغیر‌های اِستک تنها در زمان اجرای تابع ساخته می‌شوند مزایا و معایب حافظه اِستک و هیپ حافظه اِستک (Stack) دسترسی بسیار سریع به متغیر‌ها نیازی برای باز پس گیری حافظه اختصاص یافته شده ندارید فضا در زمان مورد نیاز به اندازه کافی توسط پردازنده مرکزی مدیریت می‌شود، حافظه ای نشت نخواهد کرد متغیر‌ها فقط محلی هستند محدودیت در حافظه اِستک بسته به نوع سیستم عامل متفاوت است متغیر‌ها نمی‌توانند تغییر اندازه دهند حافظه هیپ (Heap) متغیر‌ها به صورت سراسری قابل دسترس هستند محدودیتی در اندازه حافظه وجود ندارد تضمینی برای حافظه مصرفی وجود ندارد، ممکن است حافظه در زمان‌های خاص از برنامه نشت کرده و حافظه اختصاص یافته شده برای استفاده در عملیات دیگر آزاد نخواهد شد شما باید حافظه را مدیریت کنید، شما باید مسئولیت آزاد سازی حافظه های اختصاص یافته شده به متغیر‌ها را بر عهده بگیرید اندازه متغیر‌ها می‌تواند توسط تابع realloc() تغییر یابد در اینجا یک برنامه کوتاه وجود دارد که در آن متغیرها در یک حافظه اِستک ایجاد شده اند. #include <stdio.h> double multiplyByTwo (double input) { double twice = input * 2.0; return twice; } int main (int argc, char *argv[]) { int age = 30; double salary = 12345.67; double myList[3] = {1.2, 2.3, 3.4}; printf("double your salary is %.3f\n", multiplyByTwo(salary)); return 0; } ما متغیر‌هایی را اعلان کرده‌ایم که یک int، یک double و یک آرایه که سه نوع double دارد هستند. این متغیر‌ها داخل اِستک وارد و به زودی توسط تابع main در زمان اجرا حافظه مورد نیاز خود را دریافت خواهند کرد. زمانی که تابع main خارج می‌شود (برنامه متوقف می‌شود) این متغیر‌ها همگی از داخل حافظه اِستک خارج خواهند شد. به طور مشابه، در تابع multiplByTwo() متغیر twice که از نوع double است، داخل اِستک وارد شده و در زمان اجرای تابع multiplyByTwo() حافظه به آن اختصاص می‌یابد. زمانی که تابع فوق خارج شود یعنی به نقطه پایان اجرایی خود برسد، حافظه اختصاص یافته شده به متغیر‌های داخلی آن نیز آزاد خواهند شد. به طور خلاصه توجه داشته باشید که تمامی متغیر‌های محلی در این نوع تعریف تنها در طول زمان اجرایی زمانی تابع زنده هستند. به عنوان یک یادداشت جانبی، روشی برای نگه داری متغیر‌ها در حافظه اِستک وجود دارد، حتی در زمانی که تابع خارج می‌شود. آن روش توسط کلمه کلیدی static ممکن خواهد شد که در زمان اعلان متغیر استفاده می‌شود. متغیری که توسط کلمه کلیدی static تعریف می‌شود، بنابراین چیزی مانند متغیر از نوع سراسری خواهد بود، اما تنها در داخل تابعی که داخل آن ایجاد شده است قابل مشاهده خواهد بود. این یک ساختار عجیب و غریب است، که احتمالا به جز شرایط بسیار خاص نیازی به آن نباشد. نسخهٔ دیگری از برنامه فوق در قالب حافظه هیپ به صورت زیر است: #include <stdio.h> #include <stdlib.h> double *multiplyByTwo (double *input) { double *twice = malloc(sizeof(double)); *twice = *input * 2.0; return twice; } int main (int argc, char *argv[]) { int *age = malloc(sizeof(int)); *age = 30; double *salary = malloc(sizeof(double)); *salary = 12345.67; double *myList = malloc(3 * sizeof(double)); myList[0] = 1.2; myList[1] = 2.3; myList[2] = 3.4; double *twiceSalary = multiplyByTwo(salary); printf("double your salary is %.3f\n", *twiceSalary); free(age); free(salary); free(myList); free(twiceSalary); return 0; } همانطور که می‌بینید، استفاده از malloc() برای تخصیص حافظه در حافظه Heap و استفاده از free() جهت آزاد سازی حافظه تخصیص یافته می‌باشد. این مواجه شدن چیز بسیار بزرگی محسوب نمی‌شود اما کمی مبهم است. چیز دیگری که باید به آن توجه داشته باشید علامت ستاره (*) است که در همه جای کد‌ها دیده می‌شود. اینها چه چیز‌هایی هستند؟ پاسخ این سوال این است : اینها اشاره گر هستند! توابع malloc() و calloc() و free() با اشاره‌گر‌هایی مواجه می‌شوند که مقادیرشان واقعی نیست. اشاره گر‌ها نوع داده ای خاصی در C هستند که آدرس حافظه مربوطه را بر می‌گردانند. در خط ۵ متغیر twice یک متغیر از نوع double نیست، اما اشاره به یک double دارد. آن آدرس حافظه ای است که نوع double در آن بلوک از حافظه ذخیره شده است. در ++C توسط کلمه کلیدی new که خود آن نیز یک اپراتور محسوب می‌شود می‌توان حافظه ای را در Heap اختصاص داد. به عنوان مثال: int* myInt = new int(256); آدرس‌های موجود در حافظه توسط اپراتور new به اشاره‌گر مربوطه پاس داده می‌شود. به مثال زیر توجه کنید، متغیر تعریف شده در حافظه اِستک قرار گرفته است: int variable = 256; سوالی که ممکن است افراد کنجکاو از خود بپرسند این است که چه زمانی از Stack و چه زمانی از Heap باید استفاده کنیم؟! خب پاسخ این سوال اینگونه خواهد بود، زمانی که شما نیاز به یک بلوک بسیار بزرگی از حافظه دارید، که در آن یک ساختار بزرگ یا یک ارایه بزرگی را ذخیره کنید و نیاز داشته باشید که متغیر‌های شما به مدت طولانی در سرتاسر برنامه شما در دسترس باشند در این صورت از حافظه Heap استفاده کنید. در صورتی که شما نیاز به متغیر‌های کوچکی دارید که تنها نیاز است در زمان اجرای تابع در دسترس باشند و قابلیت خواندن و نوشتن سریعتری داشته باشند از نوع حافظه Stack استفاده کنید. فقط فراموش نکنید که حافظه Heap تحت توابع molloc(), realloc(), calloc() و free() مدیریت می‌شوند. هرچند اشاره‌گر های هوشمند نیز در ++C وجود دارند اما در بسیاری از مواقع که نیاز است بسیار جزئی و حساس بر روی کد‌های خود کار کنید از مدیریت حافظه به صورت دستی استفاده کنید.
  6. 1 امتیاز
    سلام، معیار‌ها می‌تونن بسیار جزئی و کاملاً فنی باشن! مثلاً بحث هزینه‌ها، ساختار، پرفرمنس‌ها، ویژگی‌ها، بحث تجاری بودن، پشتیبانی و غیره... برای مثال MySQL به خاطر سرعت بالا، پشتیبانی از چند-سکویی، پایداری خوب و همچنین پشتیبانی از لایه‌های چند منظوره و موتور‌های چند منظوره برای اهداف خاص بسیار مطرح شده، البته نسخه‌های متفاوتی دارن که جدیدا MariaDB بسیار بهتر هست. از طرفی PostgreSQL در نسخه‌های جدید‌تر از لحاظ سرعت با MySQL برابری می‌کند و به خاطر تضمین پشتیبانی از داده‌های بسیار بزرگتر نسبت به مای‌اس‌کیو‌ال و پشتیبانی از قابلیت‌های بسیار زیاد نسبت به آن مطرح هست! مخصوصاً عملکرد بهتری که در سرور‌هایی با پشتیبانی از پردازنده‌های چند هسته‌ای دارد. این دو مورد کاربرد‌های بسیار عظیمی دارند و شما می‌تونید برای اهداف بزرگ ازشون استفاده کنید. هر دوی این دیتابیس‌ها چند-سکویی هستند اما برای کار حرفه‌ای MySQL و برای کار‌های حرفه‌ای تر PostgreSQL پیشنهاد میشه. در نظر داشته باشید بهینه سازی این موارد با ترکیب مختص برای سیستم‌های کشینگ مثل Memcached و Redis بسیار چشمگیر خواهد بود. برای پروژه‌ی شما با توجه به توضیحی که دادین MySQL انتخاب خوبی هست.
  7. 1 امتیاز
    با سلام تا جایی که به خاطر میارم مایکروسافت هم دیتابیسش رو کراس کرد. ولی در کل انتخاب خوبی نیست MS SQL Server ولی برای انتخاب دیتابیس کلا توی هر پروژه ای باشه باید اول بررسی کنید و میزان نیاز واقعیتون رو مشخص کنید. مثلا اگر بخواید روی موبایل هم خروجی بدید و تمایلی به تغییر دیتابیس نداشته باشید و فقط یک یا چند کاربر به صورت متوالی از نرم افزار استفاده کنند اس کیو لایت میتونه انتخاب خوبی باشه چون روی موبایل هم جواب میده و برای کار تک کاربره (کاری که هم زمانی نداشته باشه توش ) خوبه ولی ممکنه بخواید فقط روی دسکتاپ خروجی بدید و نیاز باشه که حالت سرور داشت هباشه نرم افزار و از چندین کلاینت بهش دسترسی باشه اونطوری بهتره از Mysql یا mariadb یا ... استفاده کنید. در جایی ممکنه بحث سنگین تر باشه که لازم بشه از NOSQL استفاده کنید که البته با توجه به عنوان پروژه شما بعید میدونم لازم بشه. موفق باشید.
این صفحه از پرچمداران بر اساس منطقه زمانی تهران/GMT+04:30 می باشد
×
×
  • جدید...