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

برنامه نویسی

  • نوشته‌
    9
  • دیدگاه
    2
  • مشاهده
    1,923

مشارکت‌کنندگان این وبلاگ

امنیت در نرم افزارهای تولید شده با زبان ++C - ادامه

ادامه مقاله امنیت در نرم افزارهای تولید شده با زبان ++C

به یک شی cv-qualified  توسط یک شی cv-unqualified دسترسی پیدا نکنید!

به برنامه زیر توجه کنید، یک روش با شرایط ثابت، که برای ذخیره سازی پنهان نتایج ناشی از دورانداختن شرایط ثابت مذکور تلاش میکند، فراخوانی میشود. به دلیل آنکه کلاس S به عنوان یک ثابت اعلام شده است.

تغییر ناگهانی و جهش مقدار پنهان ذخیره شده، منجر به بروز رفتار نامشخص میگردد.

#include <iostream>
class S{
private:	
	int cachedValue;
	int compute_value() const; // expensive
public:
	S() : cachedValue(0) {}
	int get_value() const{
		if (!cachedValue){
			const_cast<S *>(this)->cachedValue = compute_value();
		}
		return cachedValue;
	}
};

void f(){
const S s;
std::cout << s.get_value() << std::endl;
}

اکنون برای رفع این مشکل کافی است که نوع متغیر عضو کلاس را به صورت mutable تعریف نماییم.

#include <iostream>
class S{
private:
	mutable int cachedValue;
	int compute_value() const; // expensive
public:
	S() : cachedValue(0) {}
	int get_value() const{
		if (!cachedValue){
			cachedValue = compute_value();
		}
		return cachedValue;
	}
};

void f(){
const S s;
std::cout << s.get_value() << std::endl;
}

 

نباید یک شی لاندا بیشتر از اشیایی رجوع شده به خود، عمر کند!

این امکان وجود دارد که عبارت لاندا، اشیای دارای مدت زمان ذخیره سازی خودکاری را از مجموعههای ازحوزه های پیوسته حوزه ی دسترسی، برای استفاده در بدنه ی تابع، رصد و دریافت کند.

ممکن است این رصد به صورت صریح و از طریق مشخص کردن شی در capture-list لاندا، یا به صورت ضمنی و با استفاده از capture-default و ارجاع به شی در بدنه ی تابع لاندا صورت پذیرد.

هنگامی که یک شی به وسیله ی کپی رصد میشود، شی لاندا شاملیک عضو داده ای غیرایستای بدون نام خواهد شد، که مقدار اولیه برابر با مقدار شی مورد رصد است.

طولعمر عضو داده ای غیرایستا نیز برابر با طول عمر شی لاندا خواهد بود. با این وجود، هنگامیکه یک شیتوسط مرجع رصد می شود، طول عمر مورد ارجاع به طول عمر شی لاندا گره نخورده است.

بنابراین هنگامیکه یک شی لاندا از شی مورد ارجاع و رصد خود بیشتر عمر کند، مادامیکه شی مورد ارجاع و رصد در دسترس است، اجرای عملگر فراخوانی تابع شی لاندا منجر به بروز رفتار نامشخص میشود.بنابراین، شی لاندا نباید طول عمری بیشتر از شی مورد ارجاع و رصد خود داشته باشد.

به مثال زیر توجه نمایید، یک مرجع لاندا، یک متغیر محلی را از یک لاندای بیرونی رصد میکند. با این وجود، طولعمر این لاندای داخلی بیشتر از لاندای بیرونی و متغیرهای محلی خودکار تعریف شده ی آن است.

هنگامیکه شی لاندای داخلی در ()f اجرا میشود، رفتار نامشخصی روی خواهد داد.

auto g(int val){
	auto outer = [val]{
		int i = val;
		auto inner = [&]{
			i += 30;
			return i;
		};
	return inner;
};
return outer();
}
void f(){
auto fn = g(12);
int j = fn();
}

برای رفع این اشکال کافی است که لاندای inner متغیر i را نه از طریق ارجاع بلکه از طریق کپی رصد نماید.

auto g(int val){
	auto outer = [val]{
		int i = val;
		//auto inner = [=] () mutable {
		//OR 	
		auto inner = [i]{
			i += 30;
			return i;
		};
	return inner;
};
return outer();
}
void f(){
auto fn = g(12);
int j = fn();
}

 

زمانی که عملگر new را سربارگذاری میکنید حتما باید عملگر delete را هم سربارگذاری نمایید

به برنامه زیر توجه نمایید، 

#include <Windows.h>
#include <new>
void *operator new(std::size_t size) noexcept(false){
	// Private, expandable heap.
	static HANDLE h = ::HeapCreate(0, 0, 0);
	if (h){
		return ::HeapAlloc(h, 0, size);
	}
	throw std::bad_alloc();
}
// No corresponding global delete operator defined.

در صورتی که هیچ کلاس کمکی برای سربار گذاری در نظر نگرفته باشید قطعا نمی توانید از عملگر delete بر روی حافظه رزرو شده توسط این تابع استفاده کنید.

بنابراین بهتره از یک کلاس پوشاننده استفاده کنیم..

#include <Windows.h>
#include <new>
class HeapAllocator{
private:	
	static HANDLE h;
	static bool init;
public:
	static void *alloc(std::size_t size) noexcept(false){
		if(!init){
			h = ::HeapCreate(0, 0, 0); // Private, expandable heap.
			init = true;
		}
		if(h){
			return ::HeapAlloc(h, 0, size);
		}
		throw std::bad_alloc();
	}

	static void dealloc(void *ptr) noexcept{
		if (h){
			(void)::HeapFree(h, 0, ptr);
		}
	}
	
};

HANDLE HeapAllocator::h = nullptr;
bool HeapAllocator::init = false;

void *operator new(std::size_t size) noexcept(false){
	return HeapAllocator::alloc(size);
}
void operator delete(void *ptr) noexcept{
	return HeapAllocator::dealloc(ptr);
}

 


عنوان منبع برنامه نویسی تدافعی در ++C


0 دیدگاه


نظرهای پیشنهاد شده

هیچ دیدگاهی برای نمایش وجود دارد.

برای ارسال دیدگاه یک حساب کاربری ایجاد کنید یا وارد حساب خود شوید

برای اینکه بتوانید دیدگاهی ارسال کنید نیاز دارید که کاربر سایت شوید

ایجاد یک حساب کاربری

برای حساب کاربری جدید در سایت ما ثبت نام کنید. عضویت خیلی ساده است !

ثبت نام یک حساب کاربری جدید

ورود به حساب کاربری

دارای حساب کاربری هستید؟ از اینجا وارد شوید

ورود به حساب کاربری
  • کاربران آنلاین در این صفحه   0 کاربر

    هیچ کاربر عضوی،در حال مشاهده این صفحه نیست.

×