PDA

View Full Version : در GetCurrentDirectory و... مشکل با پارامتر ها



r00tkit
یک شنبه 02 آبان 1389, 00:36 صبح
سلام

ببینید دوستان




DWORD WINAPI GetCurrentDirectory(__in DWORD nBufferLength,
__out LPTSTR lpBuffer
);


lpBuffer
A pointer to the buffer that receives the current directory string. This null-terminated string specifies the absolute path to the current directory.

توی این تابع و امثالهم برای پارامتر دوم چه متغییری باید تعریف کنیم که به مشکل بر نخوریم

هر sampleلی یه نوع جدا استفاده کرده

اصلا" بافر یعنی چی ؟ من ان نوعی که گفته درست می کنم ولی برنامه hang می کنه


نوعی که جواب می ده یه ارایه از TCHAR



TCHAR r[MAX_PATH]
من از



TCHAR* awBuffer=new TCHAR;استفاده می کنم heap خراب می شه

چرا ؟؟؟؟ تایع گفته یه اشاره گر از نوع LPTSTR چیز دیگه نگفته
پس باید



LPTSTR f = new TCHAR;
کار کنه ( می دونم همه اینها یکی هستن typedef) تابع که نگفته ارایه static باشه

ساعت 1 شب جواب خودم: این چیزی که من می نویسم dynamic memory allocation هستش و تا زمان اجرا اندازه ان معلوم نیست در صورتی که این جور توابع با این پارامتر اشاره گر به ارایه می خوان به اندازهی معلوم به عنوان buffer یا به عبارتی static array

دوستان(استاد موسوی) تجربشون رو بگن

r00tkit
یک شنبه 02 آبان 1389, 00:51 صبح
با توجه به این :




GetCurrentDirectory does not allocate space for the result, it's up to you to do that.
این رو نوشتم کار کرد :



LPTSTR NPath = new TCHAR[MAX_PATH];
DWORD a = GetCurrentDirectory(MAX_PATH,NPath);

wprintf(L"CURRENT DIRECTORY: %s" , NPath) ;

ولی یه سوال دیگه .......؟

جواب سوال ..... می شه ->




LPTSTR NPath = new TCHAR[1000];
فرق داره با این:




LPTSTR NPath = new TCHAR(1000);
و



LPTSTR NPath = new TCHAR;

mehdi.mousavi
دوشنبه 03 آبان 1389, 01:04 صبح
سلام.
برای اینکه اوضاع رو پیچیده تر کنیم، اجازه بدید کد زیر رو در نظر بگیریم:

TCHAR *p1 = new TCHAR;
TCHAR *p2 = new TCHAR();
TCHAR *p3 = new TCHAR[10];
TCHAR *p4 = new TCHAR(10 * sizeof(TCHAR));
TCHAR *p5 = new TCHAR[10 * sizeof(TCHAR)];

(با فرض اینکه TCHAR معادل Char باشه، یعنی یک بایت، به بیان دیگه، تو مد MBCS برنامه رو Compile کرده باشیم):


خط اول، دارم یک pointer ایجاد میکنم به خونه ای که میتونه حاوی یک بایت باشه. اینجا داره Default Constructor مربوط به TCHAR فراخوانی میشه.
خط دوم تفاوتی با خط اول نداره، چون اینجا هم دارم Default ctor رو Call میکنم و فقط یک بایت برای p2 کنار میذارم.
خط سوم، دارم یه آرایه 10 عنصری از TCHAR ها ایجاد میکنم، که p3 داره به خونه اولش اشاره میکنه. در نتیجه *p3 میشه محتوای خونه اول. به همین ترتیب، p3[3] یعنی محتوای خونه چهارم، که یه TCHAR هستش...
خط چهارم، دارم سعی میکنم گمراهتون کنم. اگر دقت کنید، دارم ctor رو Call میکنم و بهش 10 * sizeof(TCHAR) رو پاس میکنم. پس TCHAR ای ایجاد میشه که محتواش هست 10، به بیان دیگه *p4 میشه 10. اینجا فقط یک بایت برای TCHAR کنار گذاشته شده، طبیعتا نباید به خونه دوم (بطور مثال) دسترسی پیدا کنم.
خط آخر هم دارم یه آرایه ای از TCHAR ها ایجاد میکنم بطول 10 بایت، که در اون p5 داره به خونه اول اشاره میکنه. طبیعتا اجازه دارم به 9 خونه دیگه نیز دسترسی پیدا کنم.

در کل، یه حرفی رو از من یادگاری داشته باشید. سعی کنید با Pointer ها در برنامه بازی نکنید و برای هر کار جزیی حافظه Heap رو درگیر نکنید. اینجا، هیچ دلیلی وجود نداره که شما برای گرفتن حافظه، Stack رو نادیده بگیرید و به سراغ Heap برید. من برنامه هایی دیدم (در حدود چند صد هزار خط) که برنامه نویس بر این گمان بوده که اگر حافظه مورد نیازش رو از Heap بگیره، خیلی جلو میفته (تو Performance و ...) در صورتیکه دقیقا عکس این مساله رخ داده و برنامه در نهایت به زانو در اومده.

الان در این کد، شما حافظه رو new می کنید، و برای آزاد سازی حافظه، باید اونو delete کنید. همین مساله باعث میشه کد شما ناخوانا و Error-Prone بشه. چون باید مقدار بازگشتی API های مورد استفاده رو نیز بررسی کنید و در Branch های مختلف کد Memory گرفته شده رو به سیستم برگردونید. در صورتیکه اگر از ابتدا این حافظه رو از Stack تخصیص داده بودید، خودش هنگام خروج از Scope به سیستم برمی گشت و دیگه نیازی نبود شما نگران آزاد سازی حافظه باشید.

دقت کنید که حتی در برخی مواقع، ماکزیموم سایز حافظه ای که می خواهید بگیرید اینقدر کوچک هستش که مایلید اونو از Stack بگیرید، اما سایزش رو نمیدونید و توی Runtime معلوم میشه. برای این جور شرایط، دستور _alloca (http://msdn.microsoft.com/en-us/library/wb1s57t5.aspx) استفاده میشه (و جاهایی که خرده حافظه مورد نیازه). این روش رو من 11 سال پیش از Paul DiLascia (خدا رحمتش کنه، بنده خدا چند سال پیش فوت کرد) یاد گرفتم و هیچ کسی رو از اون روز تا الان ندیدم که از اون استفاده کنه.

استفاده از _alloca در واقع زدن دو نشون با یه تیر هستش: اول اینکه دیگه نیازی نیست نگران آزاد کردن Memory باشید، چون حافظه بطور خودکار پس از خروج از Function به سیستم برمیگرده، ثانیا Heap رو درگیر فضاهای کوچک نکرده اید تا اونو به زحمت بندازید. برای آشنایی با جزییات مربوط به Stack نیز می تونید به این آدرس (http://msdn.microsoft.com/en-us/library/x4ea06t0.aspx) رجوع کنید.

موفق باشید.

پاورقی: از این پس هر وقت خواستید منو مورد خطاب قرار بدید، لطفا بهم خبر بدید. بخدا من فرصت ندارم همه پستها رو بخونم که شما همینطوری توی پستهاتون اسم منو میارید و منو مورد خطاب قرار میدید. :)