PDA

View Full Version : خطای out of memory while expanding memory stream



m-khorsandi
سه شنبه 04 دی 1386, 13:22 عصر
سلام به دوستان،
من یه فایل 900 مگابایتی رو از روی Serverیی با کمک Stream میخوام بخونم و روی کلاینتی نمایش بدم. مشکل اینجاست که وقتی یه نمونه برنامه می‌نویسم، بدون هیچ مشکلی اجرا میشه ولی وقتی همون کد را به برنامه‌ی اصلی میبرم پیغام خطای out of memory while expanding memory stream رو میگیرم.
اگه کسی با این پیغام خطا سر و کار داشته یا اینکه راه حلی به نظرش میرسه، ممنون میشم در اختیار من قرار بده.

JAFO_IRAN
سه شنبه 04 دی 1386, 13:31 عصر
سلام

قاعدتا دارید از memory stream استفاده میکنید. این object برای این حجم شاید مناسب نباشد. بالاخره حافظه ماشین حدی داره...
دلیل اینکه در برنامه اصلی خطا میگیرید اینه که در زمان اجرای برنامه اصلی احتمالا حافظه بیشتری مصرف شده و حافظه کمتری برای stream باقی مونده.
راهی نداره که اطلاعات رو توی یک tmp file بریزید (مثلا با file streamای چیزی)؟

ارادت

m-khorsandi
سه شنبه 04 دی 1386, 13:47 عصر
من از TFileStream استفاده میکنم،
منظورتون از tmp file چیه؟

Inprise
سه شنبه 04 دی 1386, 16:38 عصر
این object برای این حجم شاید مناسب نباشد. بالاخره حافظه ماشین حدی داره...
دلیل اینکه در برنامه اصلی خطا میگیرید اینه که در زمان اجرای برنامه اصلی احتمالا حافظه بیشتری مصرف شده و حافظه کمتری برای stream باقی مونده.روی User Mode "حداقل" دو گیگ برای Allocation در عادی ترین حالت داره ، و بعیده برنامهء اصلی اش 1.1 گیگ باشه !


پیغام خطای out of memory while expanding memory stream رو میگیرماین خطا رو چه زمانی میگیری ؟ از استک استفاده میکنی یا هیپ ؟ و از کدام نسخهء دلفی استفاده میکنی ( FastMM ) ؟ این چند صد مگابایت اطلاعات مربوط به چه چیزی هست ؟ چطور در حال پردازش و نمایشش هستی ؟

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

JAFO_IRAN
سه شنبه 04 دی 1386, 17:13 عصر
سلام



روی User Mode "حداقل" دو گیگ برای Allocation در عادی ترین حالت داره ، و بعیده برنامهء اصلی اش 1.1 گیگ باشه !

حالا حتما که ماشین 2 گیگ حافظه اصلی و virtual خالی نداره که به یک برنامه بده؛ عادی ترین حالت برای ما اینه که ماشینمون 512 مگابایتی باشه، user هم Page file درست و حسابی نذاشته باشه کلی هم task روی ماشین در حال اجرا باشه. همانطور که قبلا هم گفتم، بالاخره حدی داره. ولی اول ببینیم منشا خطا چیه (حالا که خودشون از memory stream استفاده نمیکنند)...

برای خواندن داده های blob field مثلا با SaveToStream، حتما در خود DataSet یک BlobStream تشکیل میشه که قاعدتا باید منشاء خطا باشه...

خطایی که شما گرفتید از متد Realloc از TMemoryStream گرفته میشه. اونجا هم از GlobalAllocPtr و GlobalReallocPtr استفاده شده که قاعدتا نوع حافظه رو از همون متغیر HeapAllocFlags مشخص میکنه که اگه بهش دست نزده باشید GMEM_MOVABLE میشه که حالت عادیه. حالا ممکنه در بقیه بخشهای برنامه یک کدی داشته باشید که این تنظیم رو عوض کنه که اونوقت به قول Inprise باید ببینیم استک استفاده شده یا نه....

فرض میکنم از ADODB استفاده میکنید؛ اونجا یک ADOBlobStream استفاده میشه که دقیقا از MemoryStream مشتق شده ولی نکته اینجاست که Realloc رو بازنویسی کرده. یعنی اگر هم حافظه کم بیاره باید از این خطاهای سیستمی بده، نه یک خطای دلفی.

به هر حال تقریبا معلومه که مشکل چیه، ولی راه حل آنی به نظرم نمیرسه؛ شاید بشه به صورت سطح پایین‌تر (مثلا با بررسی کد ADOBlobStream) بدون تشکیل Stream واسط هم داده‌ها رو خوند ولی شک دارم....

ارادت
پ ن : من یکبار تقریبا همین داستانها رو نوشته بودم ولی مثل اینکه پاک شده یا browser من قاطی کرده؛ به هر حال اگه پست تکراری شد قبلا پوزش میخوام...

m-khorsandi
چهارشنبه 05 دی 1386, 10:53 صبح
این خطا رو چه زمانی میگیری ؟ از استک استفاده میکنی یا هیپ ؟ و از کدام نسخهء دلفی استفاده میکنی ( FastMM ) ؟ این چند صد مگابایت اطلاعات مربوط به چه چیزی هست ؟ چطور در حال پردازش و نمایشش هستی ؟خطا رو به محض اجرای FileStream.LoadFromFile میگیرم(در ادامه بیشتر توضیح میدم)، از هیپ و دلفی 5 استفاده میکنم و اطلاعات مربوط به یک عکس از یک سری نقشه هست و دارم سعی میکنم که با ImageEn نمایشش بدم.

خطا رو به محض اجرای FileStream.LoadFromFile میگیرم، یعنی حتی 1 ثانیه زمان صرف خواندن اطلاعات نمیشه و به سرعت پیغام خطا میده، کد به شکل زیر هست تقریباً:



var
Strm: TّFileStream;
begin
Strm := TMemoryStream.Create('\\AServer\File_0001.Jpg', fmOpenRead or fmShareDenyWrite);

end;
این اطلاعات دقیقاً روی یک مسیر روی Server هست و توی جدول توی دیتابیس قرار نداره.

m-khorsandi
چهارشنبه 05 دی 1386, 11:17 صبح
به نظرتون اصلاً صحیح هست که این حجم از اطلاعات (که میتونه بیشتر هم باشه و هم میتونه تعداد کاربرانی که این فایل‌های حجیم رو لود میکنند زیاد باشه ) یکجا خوانده بشه؟

Inprise
چهارشنبه 05 دی 1386, 12:12 عصر
میتونی خروجی دیباگر در لحظه وقوع خطا رو بگذاری اینجا ؟
( یه سری ایده هست اما این اول از همه لازمه )

JAFO_IRAN
چهارشنبه 05 دی 1386, 15:17 عصر
سلام

1. قاعدتا من هنوز با ترم‌هایی که بقیه دوستان بکار میبرند آشنا نیستم به همین دلیل پرت میافتم.

2. تازه فهمیدم که اصلا Data Baseای درکار نیست و منظور از سرور اونی نبوده که من فهمیدم.

3. تا حالا اینقدر احساس شفاف بودن نکرده بودم.

4. هنوز هم فکر میکنم مشکل در استفاده از MemoryStream برای این حجم از داده‌ها است. انتقال این حجم داده اصلا غیرممکن نیست ولی FileStream و استفاده از tmp file (همون فایل موقت یا temporary) توصیه میشه. شما میگید از FileStream استفاده میکنید، اما هم constructor در کد نمونه مربوط به MemoryStream هستش و هم اینکه FileStream اصولا متدی به نام LoadFromFile نداره.

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

ارادت

m-khorsandi
چهارشنبه 05 دی 1386, 15:21 عصر
4. هنوز هم فکر میکنم مشکل در استفاده از MemoryStream برای این حجم از داده‌ها است. انتقال این حجم داده اصلا غیرممکن نیست ولی FileStream و استفاده از tmp file (همون فایل موقت یا temporary) توصیه میشه. شما میگید از FileStream استفاده میکنید، اما هم constructor در کد نمونه مربوط به MemoryStream هستش و هم اینکه FileStream اصولا متدی به نام LoadFromFile نداره.

درسته، اون خط رو با عجله نوشتم و اون اشتباه پیش اومد.