PDA

View Full Version : سوال: مفهوم stack overflow



deCODER-
سه شنبه 26 اسفند 1393, 12:53 عصر
درود و شادباش به مناسبت روز چهارشنبه سوری رو از من بپذیرید:قلب:

میخوام مفهوم stack overflow رو با ذکر یک مثال بدونم.

تشکر

reza_noei
سه شنبه 26 اسفند 1393, 14:13 عصر
درود و شادباش به مناسبت روز چهارشنبه سوری رو از من بپذیرید:قلب:

میخوام مفهوم stack overflow رو با ذکر یک مثال بدونم.

تشکر

سلام.
هر برنامه از چند سمت تشکیل میشه :
1- کد
2- داده
3- پشته (stack)
هر کدام از این بخشها محدوده ای از حافظه رو اشغال میکنن به این بخش ها اصطلاحاً سگمنت میگویند.
واضح است که کد و داده حجم ثابتی دارند و توسط برنامه نویس نوشته میشوند.
اما قسمت پشته حافظه ایه که به صورت پویا رشد میکنه. مثلا شما یک تابع رو به زبان سی نوشته اید و آنرا n بار فراخوانی کرده اید.
داده های برنامه که در محل جدا گانه ای توسط شما تعریف شده پس متغییرهای موجود در توابع ما در کجا ذخیره شوند ؟
اینجاست که کاربرد پشته برای ما اهمیت پیدا میکنه، حافظه ای که بتوان در صورت نیاز از فضای آن استفاده نمود و بتوان آنرا آزاد نمود.
گاهی اوقات برنامه ما پا را از حد فراتر میگذارد و شروع به اشغال حافظه پشته میکند تا جایی که تمام حافظه
پشته را مصرف میکند. این کار با توجه به وسعت حافظه پشته معمولا بواسطه بروز حلقه های بینهایت در ایجاد شی ها از کلاسی و یا موارد این چنینی اتفاق می افتد
و باعث سرریز شدن حافظه پشته (stack overflow) میشود.

احسان!
سه شنبه 26 اسفند 1393, 16:54 عصر
سلام.
(حافظه پشته، هربرنامه 64 کیلوبایت است)
۶۴ کیلوبایت نیست!
حداکثر اندازه ی حافظه ی پشته ای که به یه برنامه اختصاص داده میشه بسته به سیستم عامل و تنظیماتش، کامپایلر و ... میتونه متفاوت باشه. معمولا در حد چند مگابایت هستش.(مثلا دو مگابایت)

احسان!
سه شنبه 26 اسفند 1393, 17:02 عصر
میخوام مفهوم stack overflow رو با ذکر یک مثال بدونم.


به طور خلاصه برخی از اطلاعات برنامه(مثل متغییر های محلی) توی یه نوع ساختمان داده توی حافظه به اسم پشته(stack) ذخیره میشن. این پشته اندازه ی محدودی داره. اگه بیشتری از اندازه اش سعی کنی توش اطلاعات ذخیره کنی سرریز(overflow) میکنه.
مثال؟ چیزی میخواید که استک اوور فلو کنه؟ اینطوری میشه:


#include <iostream>

void stackOverFlow(){
std::cout << "Trying to get a stack overflow!" << std::endl;
stackOverFlow ();
}

int main()
{
stackOverFlow ();
}

deCODER-
سه شنبه 26 اسفند 1393, 22:36 عصر
به طور خلاصه برخی از اطلاعات برنامه(مثل متغییر های محلی) توی یه نوع ساختمان داده توی حافظه به اسم پشته(stack) ذخیره میشن. این پشته اندازه ی محدودی داره. اگه بیشتری از اندازه اش سعی کنی توش اطلاعات ذخیره کنی سرریز(overflow) میکنه.
مثال؟ چیزی میخواید که استک اوور فلو کنه؟ اینطوری میشه:


#include <iostream>

void stackOverFlow(){
std::cout << "Trying to get a stack overflow!" << std::endl;
stackOverFlow ();
}

int main()
{
stackOverFlow ();
}




1-آیا استنباط من از حرف های شما درسته؟:
هر متغیری که ما در برنامه خودمونیم تعریف میکنیم مثلا int x = 3; در منطقه ای از توالی خانه های حافظه که فضای محدودی دارن ، به نام "پشته" ذخیره میشن.

2- در این مثالی که شما زدید ، هیچ متغیری تعریف نکردید که بخواد تو حافظه پشته ذخیره بشه. پس چطور ممکنه stack overflow رخ بده؟

احسان!
چهارشنبه 27 اسفند 1393, 10:11 صبح
1-آیا استنباط من از حرف های شما درسته؟:
هر متغیری که ما در برنامه خودمونیم تعریف میکنیم مثلا int x = 3; در منطقه ای از توالی خانه های حافظه که فضای محدودی دارن ، به نام "پشته" ذخیره میشن.

2- در این مثالی که شما زدید ، هیچ متغیری تعریف نکردید که بخواد تو حافظه پشته ذخیره بشه. پس چطور ممکنه stack overflow رخ بده؟

۱: اسم اون پشته نیست. یه ساختمان داده هستش توی حافظه که از جنس پشته هستش.(البته خیلی اوقات دیدم همون اسم پشته هم رایجه.)راجع به پشته ی فراخوانی تحقیق کنید.(در حال حاضر مثال نقضی سراغ ندارم که پشته نباشه.)

۲: فقط متغییر ها نیستن. توابع هم شامل اطلاعاتی مثل مکان پیاده سازی کدشون، آرگومان ها و ... میتونن باشن.(بستگی به کامپایلر و معماری و سیستم عامل میتونه داشته باشه.) هنگام صدا زدن یه تابع، تابع به خطی که کدش اونجا است میره و بعد از اتمام کد به جایی که تابع فراخوانی شده بر میگرده. طبعا ذخیره ی این جور اطلاعات(مثلا جایی که تابع فراخوانی شده بود.) نیازمند حافظه هستش.

deCODER-
چهارشنبه 27 اسفند 1393, 13:11 عصر
۱: اسم اون پشته نیست. یه ساختمان داده هستش توی حافظه که از جنس پشته هستش.(البته خیلی اوقات دیدم همون اسم پشته هم رایجه.)راجع به پشته ی فراخوانی تحقیق کنید.(در حال حاضر مثال نقضی سراغ ندارم که پشته نباشه.)

۲: فقط متغییر ها نیستن. توابع هم شامل اطلاعاتی مثل مکان پیاده سازی کدشون، آرگومان ها و ... میتونن باشن.(بستگی به کامپایلر و معماری و سیستم عامل میتونه داشته باشه.) هنگام صدا زدن یه تابع، تابع به خطی که کدش اونجا است میره و بعد از اتمام کد به جایی که تابع فراخوانی شده بر میگرده. طبعا ذخیره ی این جور اطلاعات(مثلا جایی که تابع فراخوانی شده بود.) نیازمند حافظه هستش.

یعنی کل کدی که ما مینویسیم که در اختیار سی پی یو قرار بگیره ، در حافظه ذخیره میشه (علاوه بر متغیر ها)؟ چون همین قبلا برای من سوال بود تو همین تالار پرسیده بودم گفتن کل کد ما تو حافظه قرار نمیگیره الان با این حرف شما کمی سردرگم شدم.

reza_noei
چهارشنبه 27 اسفند 1393, 14:27 عصر
یعنی کل کدی که ما مینویسیم که در اختیار سی پی یو قرار بگیره ، در حافظه ذخیره میشه (علاوه بر متغیر ها)؟ چون همین قبلا برای من سوال بود تو همین تالار پرسیده بودم گفتن کل کد ما تو حافظه قرار نمیگیره الان با این حرف شما کمی سردرگم شدم.

سلام.
مسئله خیلی سادست بدلیل محدود بودن حافظه اصلی (RAM) ما نمیتوانیم بیشتر از ظزفیت آن برنامه در حال اجرا داشته باشیم. امّا اگر بخواهیم این امکان را داشته باشیم چه کنیم ؟ سیستم عامل اینجاست که وارد عمل میشود. سیستم عامل برنامه ها را به صفحاتی از حافظه تقسیم میکند فرض کنید یک برنامه 700 مگابایتی به قسمت های (مثلاً) 50 مگابایتی تبدیل شود. حال سیستم عامل از طریق مکانیزم هایی صفحاتی را که کمتر مورد استفاده قرار گرفته است را به حافظه جانبی (HDD) منتقل میکند. به این ترتیب میتوانیم حجم بیشتری از برنامه های در حال اجرا را داشته باشیم. در نظر داشته باشید که اگر زمانی برنامه به کدهای منتقل شده به حافظه جانبی نیازمند باشد سیستم عامل آن صفحه را بر روی حافظه اصلی بارگزاری میکند تا اجرا شود.
پشته مرتباً مورد استفاده برنامه ماست جزو اون صفحات کم کاربرد برنامه ما محسوب نمیشود پس تا پایان برنامه در حافظه اصلی قرار میگیرد.(از طرفی کدی که دوستمون نوشتند آنقدری نیست که دچار صفحه بندی شود)
به این ترتیب با فراخوانی مرتب تابع توسط خودش آدرس تابع والد در پشته ذخیره شده و باعث پرشدن این حافظه و در نتیجه سرریز شدن پشته میشود.

احسان!
چهارشنبه 27 اسفند 1393, 15:45 عصر
یعنی کل کدی که ما مینویسیم که در اختیار سی پی یو قرار بگیره ، در حافظه ذخیره میشه (علاوه بر متغیر ها)؟ چون همین قبلا برای من سوال بود تو همین تالار پرسیده بودم گفتن کل کد ما تو حافظه قرار نمیگیره الان با این حرف شما کمی سردرگم شدم.
فکر کنم کمی بد توضیح دادم.
کل کد نه.(تا جایی که میدونم.) ولی طبعا بخش هایی از اطلاعات موجود در کد در حافظه قرار میگیره.این اطلاعات شامل چیزهایی مثل همون متغییر ها، مکانی که توابع فراخوانی شدن و ... میتونه باشه.