sizeof برای اشاره گر ها - هفت خط کد انجمن پرسش و پاسخ برنامه نویسی

sizeof برای اشاره گر ها

+3 امتیاز
مقدار برگشتی sizeof برای اشاره گر ها فقط اندازه سایز پوینتر هست چرا sizeof نمی تونه تعداد خونه هایی که new شده رو برگردونه ؟!

وقتی که sizeof درست کار نمی کنه delete[] چطوری میتونه تشخیص بده که چند بایت گرفته شده که اندازه همون تعداد حافظه رو پاک کنه ؟
سوال شده مرداد 28, 1393  بوسیله ی علیرضا حقجو (امتیاز 32)   1 3 5
خب sizeof برای این کار درست نشده. ظاهرا هیچ راهی در C++‎ برای گرفتن میزان حافظۀ پویا وجود نداره:
http://stackoverflow.com/questions/12617244/finding-size-of-dynamically-allocated-array
تابع _msize که در فایل malloc.h هست، سایز حافظه ی اختصاص داده شده با malloc و یا calloc و یا realloc رو برمیگردونه.
_msize رو ندیده بودم ! فک میکردم که آخه چرا malloc یه تابع برای اندازه حافظه نداره ! :)
مطمئن بودم که همچین تابعی باید وجود داشته باشه...رفرنس c++builder و MSDN رو برای malloc  و free و realloc که نگاه می کردم اینو پیدا کردم. واقعا رفرنس ها خیلی مهمن. دمشون گرم.

1 پاسخ

+6 امتیاز
 
بهترین پاسخ

توی ++C نوع های داده ای (Datatype ها ) مثل int , float , char , .... وجود دارن که هرکدوم اندازه مشخصی دارن .

sizeof اندازه این نوع ها رو بهتون برمیگردونه . اگر از یک کلاس sizeof بگیرید ، اندازه مجموع نوع های داده ای رو بهتون میده .

ولی در مورد اشاره گر ها داستان جدایی هست .

جواب توی لینک stackoverflow.com هم درسته هم غلط .

درسته به دلیل اینکه مثلا شما با new میخواهید ۹ بایت حافظه بگیرید و new از تابع ()malloc حافظه رو درخواست میکنه .

و اینکه شما دارید از کدوم Implementation ای از malloc استفاده میکنید تعیین میکنه که حافظه چطور اختصاص بگیره .

 ( پیاده سازی توابع ()malloc و ()free و realloc متفاوت هست . مثلا کتابخونه GNU C از مدیریت حافظه ی ptmalloc2 استفاده میکنه .

کتابخونه ی MSVCRT‌ رو یادم نیست که از کدوم مدیریت حافظه استفاده میکرد . مدیریت حافظه ها یی مثل tcmalloc و nedmalloc و jemalloc  و ... هم وجود دارن که پیاده سازی برای ()malloc هستند  )

و اینطوری Memory Allocator ها اندازه درخواستی شما رو Align میکنن ( برای بالابردن Performance ) و مثلا اندازه درخواستی شما رو که ۹ بوده رو به ۱۶ تبدیل میکنن . پس شما اگر مثلا ۹ تا حروف رو درخواست کرده بودید . درواقع به شما بلاکی به اندازه ۱۶ حروف میده ( به دلیل Alignment ) . پس بلاک شما ۱۶ بایتی هست نه ۹ بایتی .

و غلطه بخاطر اینکه اطلاعات مربوط به بلاکی که ایجاد شده رو پشت بلاک ایجاد شده قرار میدن (مثل اندازه و موارد دیگه ) .

که در مواقع آزاد کردن حافظه Memory Allocator اندازه بلاک رو داشته باشه تا بتونه بلاک رو آزاد کنه .( که نهوه ذخیره Meta های یک بلاک
در هر پیاده سازی متفاوت هست )

درواقعا اون حافظه ی Stack هست که اندازه ی هر متغییر داخلش دخیره نمیشه . در مورد Heap اینطور نیست . Heap نیاز به سازمان دهی خیلی قوی داره .

شما متونید با به سادگی با ایجاد یک ساختار ساده تعداد آرایه رو هم برای خودتون نگه داری کنید .

مثلا :

#include <iostream>
 
using namespace std;

struct Array
{
	size_t count;
	short* items;
};

template <typename T>
class Array2
{
public:
	size_t count;
	T* items;
};

int main ()
{
	Array a = { 10 , new short[10] };
	Array2<float> b { 30 , new float[30] };
	size_t i = 0;

	for(i = 0;i < 10;i++)
		a.items[i] = i * i;

	for(i = 0;i < 30;i++)
		b.items[i] = i * 3.14f;

	for(i = 0;i < 10;i++)
		cout<<a.items[i]<<endl;

	for(i = 0;i < 30;i++)
		cout<<b.items[i]<<endl;

	return 0;
}

 

شما تو طول برنامه تعداد آرایه ها رو داخل متغییر های count دارید .

پاسخ داده شده مرداد 29, 1393 بوسیله ی Ali Rahbar (امتیاز 4,240)   6 16 46
انتخاب شد مرداد 29, 1393 بوسیله ی علیرضا حقجو
سلام!
ممنونم از پاسختون...
در مورد این که گفتید "... اطلاعات مربوط به بلاکی که ایجاد شده رو پشت بلاک ایجاد شده قرار میدن (مثل اندازه و موارد دیگه ) ..." می شه یه مثال بزنید که چه جوری می شه این اطلاعات رو به دست آورد و استفاده کرد؟ مثلا چه طوری می شه اندازه ی در نظر گرفته شده رو از این راه به دست آورد؟...
ببینید . همونطور که گفتم شما باید بدونید اون implementation این اطلاعات رو کجا و به شکل ذخیره میکنه . برای مثال یه پیاده سازی از malloc میتونه اندازه بلاک رو توی ۴ بایت پشت آدرس بلاک ذخیره کنه . و شاید از اون ۴ بایت ۳ بیتش رو برای چیز دیگه ای در نظر بگیره .
و به خاطر همین روش Portable ی نیست که من بخوام بهتون بگم .
شما باید کد malloc ی کد رو الان دارید ازش استفاده میکنید رو بگیرید و بررسی کنید تا متوجه ساختارش بشید .
مثلا اگر اندازه بلاک توی ۴ بایت پشت آدرس بلاک ذخیره شده باشه شما آدرسی که از new میگیری رو -4 میکنی و اونموقع میتونی اندازه بلاک رو داشته باشی .
فقط اینو بگم که اینها مثال هستند . و شما باید برای هر پیاده سازی malloc بدونی که metaهاش کجا و چجوری ذخیره میشن .
...