الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

[ تمت الإجابة ]أريد حجز مصفوفة بحجم غيغا بايت..

مغلق
بدأه مصطفى 36a2 في 9 يوليو 2012 · 14 رد · 1,526 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

بسم الله الرحمن الرحيم ..

منذ عشر دقائق فقط ... تنبّهت إلى أن مليون بايت هي مجرد 1ميغا بايت وليست 1غيغا بايت ...

مما يعني أنني الآن أشعر بالرغبة لأعض أي شخص يقف في طريقي laugh.gif.. لأنني الآن قادر على التعامل مع رقم من مليار منزلة ..إن تمّت الإجابة عن سؤالي ...

وببساطة السؤال كما يلي :

أريد السطر المفقود ( أو العدة أسطر المفقودة) والتي تجعل الكود التالي يعمل بحيث يحجز مليار بايت دون مشاكل ويعطيني حرية التصرف بها كيفما أريد ...

void main()
{
char Giga[1000000000];
}

حسناً ... وسيتم ترشيح الإجابة بعد تجربة الطريقة .. ولو عندي 1000نقطة ما بقصّر smile.gif

ولكن أريد بالفعل إجابة كاملة مشروحة بشكل جيد ..

فالموضوع لا يقبل التجربة خصوصاً مع النظام ... صرلنا سنة ونص ماكنا نخلص من النظام عندنا...054.gif

من لديه إجابات من قبيل : هذا مستحيل.. وأنت تهدد الأمن العالمي ..و سوف تموت لمجرد التفكير بذلك...إلخ إلخ ..

فأرجو أن يحاول البحث عن إجابة أخرى .. فقد تعاملت مع النوع السابق من الإجابات كحقيقة مطلقة لمدة 6أشهر ... والآن أشعر بالرغبة للعض كما أخبرتكمlaugh.gif ...

فأنا متحمّس لمعرفة الإجابة ..200.gif200.gif049.gif200.gif200.gif

نظريّا لا يوجد مانع ذاكرة الرام عندي 2غيغابايت... ولا يوجد سوى حجم الStack الذي يُفرض على البرنامج ... فمن يعرف كيف يتخطّى الحدود؟؟

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 9 يوليو 2012 في 16:39

1 −1
#2

يمكنك بدل أن تستخدم مصفوفة عادية أن تخصص مصفوفة عن طريق malloc أو calloc. لو عملت :

char array_one[10];
char *array_two = (char *) malloc(sizeof(char) * 10);

ستحصل على مصفوفتين بنفس الحجم ولكن حجم الأولى في المكدس 10 بايت والأخرى 4 بايت فقط وثابتة مهما كبر حجم المساحة المحجوزة وذلك لأنها موشر :

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char **argv) {

    char array_one[10];

    char *array_two = (char *) malloc(sizeof(char) * 10);
    if( array_two == NULL ) {
        fprintf(stderr, "Error: can't allocate the memory\n");
        return(-1);
    }

    printf("array_one = %d\n", sizeof(array_one));
    printf("array_two = %d\n", sizeof(array_two));

    free(array_two);
    return(0);
}

array_one = 10
array_two = 4

ولكن تأكد دوماً من عمل casting , إستخدم :

(char*)

أو أي نوع آخر مثل :

(int *)

إذا لم يكن نوع المصفوفة char وذلك لأن malloc تعيد مؤشر عام نوعه :

void *

.

وتحقق أيضاً من أنها لم تفشل, فستعيد NULL إذا فشلت. وقم دوماً بإستداء free لإلغاء حجز لذاكرة متى ما إنتهيت من المصفوفة.

عموماً العمل مع مصفوفات بهذه الأحجام غالباً ما يعني أن هناك خلل وسوء تصميم في البرنامج.

تم تعديل هذه المشاركة بواسطة Mr.B في 9 يوليو 2012 في 22:19

#4

عزيزي, ليس هناك فائدة مما تريد عمله لأنك تستخدم الـ stack في غير ما استحدثت لأجله أصلاً. الموضوع يعتمد على نظام التشغيل و المترجم(في الحقيقة الـ Linker) الذي تعمل عليه. عندما تقوم بترجمة برنامج فإن الـ Linker يقوم ببناء Header لملفك التنفيذي, و هذا الـ header يستخدم من قبل نظام التشغيل لمعرفة إعدادات تشغيل ملفك التنفيذي. في Visual Studio, يمكنك تغيير حجم الـ stack الافتراضي:

/STACK:size_in_bytes

في GCC:

--stack,size_in_bytes

على العموم, يمكنك تغيير حجم الـ stack حتى وقت التشغيل من خلال دوال نظام التشغيل, و لكن تذكر أن حجز كمية كبيرة من الذاكرة على الـ stack هو أسلوب خاطئ في الأصل, هي صممت لكي تكون مخزن مؤقت و سريع للدوال.

تحياتي...

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 10 يوليو 2012 في 11:28

2
#5

الـ Stack: هو مكان بالذاكره لابد من تحديد المساحة التى سيتم حجزها به وقت ترجمة البرنامج، هذا الجزء من الذاكره يحتوى على المتغيرات التى تم تعريفها داخل الكود أيا كان نوع هذه المتغيرات (ماعدا المتغيرات العامه) و أيضا المصفوفات التى تم تحديد حجم لها بشكل مباشر أو غير مباشر، أيضا تحتوى هذه الذاكره على شجرة إستدعاءات الدوال و قيم المعاملات. هذه الذاكره يتم تحريرها بمجرد العوده للداله التى قامت بالإستدعاء او بمجرد الإنتهاء من تنفيذ الداله الحاليه.

إذا فالسؤال غير منطقي من الناحية البرمجية ! :)

1 −1
#6

السلام عليكم .

اخي هاذا ممكن بشكل بسيط ولكن في ال heap . اي تستخدم Dynamic Alloation

و عند امتلاء الرام سيضطر نظام التشغيل الى استخادم ال Paging اي تخزين هذه المعلومات

على شكل Pages على الهارد ديسك بدلا من الرام و من ثم التبديل بين هذه ال Pages ولكن

هذا سيؤثر على سرعة النظام ككل .

و بالتالي حلك بسطر واحد .

char * Giga = new char [1000000000] ;

تم تعديل هذه المشاركة بواسطة montaser00 في 10 يوليو 2012 في 19:43

#7

أستاذي B شكراً لردك ... بالنسبة لإجابتك فإن العملية new أصلاً ليست عملية مستقلة فهناك مكتبة كاملة malloc تستدعيها العملية new وعلى أي حال لا يمكننا حجز خارج الstack

في الحقيقة أضفت إلي معلومة جديدة .. ولكن لم أعلم فائدتها في ما أريد ..

اقتباس
عموماً العمل مع مصفوفات بهذه الأحجام غالباً ما يعني أن هناك خلل وسوء تصميم في البرنامج.

لا أنكر ذلك ... ولكن هذا لا يعني أنني لن أحتاج ذلك بعد تطوير الخوارزمية بأكبر قدر ممكن ...

أخي أحمد شلبي ..

اقتباس
ولكن أريد بالفعل إجابة كاملة مشروحة بشكل جيد ..
وأشكرك على الرابط .. ولكن كما قلت أريد إجابة بالعربي مشروحة ... أشكرك على الرد...

أستاذي الفاضل خالد الشايع.. أنت أكثر من فهم عليّ..

اقتباس
ليس هناك فائدة مما تريد عمله لأنك تستخدم الـ stack في غير ما استحدثت لأجله أصلاً.

أنا أريد أن أستخدم ذاكرة الوصول لها بنفس سرعة الوصول للرام ... أريد السرعة والحجم الكبير ... لا مشكلة لدي stack البرنامج أو غيرها ... أريد 1غيغا من الرام بأي طريقة...

اقتباس
لأنك تستخدم الـ stack في غير ما استحدثت لأجله أصلاً.

طالما نستخدم كل شيء لما استُخدم له ... فسنبقى في مجال التطبيقات المُعتادة ... wink.gif

اقتباس
على العموم, يمكنك تغيير حجم الـ stack حتى وقت التشغيل من خلال دوال نظام التشغيل

حسناً .. هذا هو السؤال كيف؟وما هي الدوال .. أنا لا أبحث عن الوصول الخاطئ أريد حجزاً نظامياً لحجم كبير ...

اقتباس
لكن تذكر أن حجز كمية كبيرة من الذاكرة على الـ stack هو أسلوب خاطئ في الأصل, هي صممت لكي تكون مخزن مؤقت و سريع للدوال.

حسناً ... أشكرك على النصيحة ... laugh.giflaugh.gif

أخي خالد ..

اقتباس
الـ Stack: هو مكان بالذاكره لابد من تحديد المساحة التى سيتم حجزها به وقت ترجمة البرنامج، هذا الجزء من الذاكره يحتوى على المتغيرات التى تم تعريفها داخل الكود أيا كان نوع هذه المتغيرات (ماعدا المتغيرات العامه) و أيضا المصفوفات التى تم تحديد حجم لها بشكل مباشر أو غير مباشر، أيضا تحتوى هذه الذاكره على شجرة إستدعاءات الدوال و قيم المعاملات. هذه الذاكره يتم تحريرها بمجرد العوده للداله التى قامت بالإستدعاء او بمجرد الإنتهاء من تنفيذ الداله الحاليه.

تماماً ... هذا ما أعرفه عن الStack ... ولكن لم سؤالي غير منطقي ..

سؤالي حسب تعريفك هو : كيف يتم تحديد مساحة الStack عند ترجمة البرنامج بحيث تكون 1giga

لازلت ..أنتظر إجابة ..

أشكر الجميع على الردود ...

والسلام عليكم ...

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 11 يوليو 2012 في 19:09

#8

أخي منتصر ...

كما أنني استغرقت 6أشهر لأنتبه أن مليون بايت هي ميغا بايت ...

فيبدو أنني استغرقت سنة .. لكي يخطر على بالي هذا الحل ..البسيط ...

سيبقى عليّ الآن أن أجربه .. إن ظهرت لي أي مشكلة تتعلق بالحجز ... فسألغي الترشيح كما اتفقنا .. بأن الترشيح بعد التجربة ...

حسناً ... وفق هذا فإن إجابة السيد B صحيحة أيضاً ... أعتذر على خطأ التقييم ...

انتظروا التجربة ... يوم الجمعة ننهي الأمر ...

أظن أن الأستاذ خالد الشايع سيعترض على خطأ السؤال ...(نعم معه حق )ولكن هذا هو السؤال على أي حال:

اقتباس
أريد السطر المفقود ( أو العدة أسطر المفقودة) والتي تجعل الكود التالي يعمل بحيث يحجز مليار بايت دون مشاكل ويعطيني حرية التصرف بها كيفما أريد

جزاكم الله خيراً ...

والسلام عليكم

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 10 يوليو 2012 في 20:46

#9

ما سبب هذا الخطأ وكيف يمكن تجنبه ؟

terminate called after throwing an instance of 'std::bad_alloc'

ليكون الحل

char * Giga = new char [1000000000] ;

صحيحاً ؟؟

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 10 يوليو 2012 في 20:47

#10
مصطفى 36a2 كتب:

ما سبب هذا الخطأ وكيف يمكن تجنبه ؟

terminate called after throwing an instance of 'std::bad_alloc'

ليكون الحل

char * Giga = new char [1000000000] ;

صحيحاً ؟؟

اخي انا جربت الحل و اعطيت كل عناصر المصفوفة قيم و الأمر كان طبيعي.

و لكن ما الذي تحاول فعله . ربما لو اعطيتني الهدف من البرنامج سأفيدك بطريقة اخرى .

اذا كان هدفك الأعداد الكبيرة فهناك طريقة افضل من ان تحجز غيغا بايت لهذا الغرض .

انظر الموضوع التالي عن .

BigInteger

او اذا اردت انا انصح بال Linked List و سيكون رقمك مركب تركيب اي ان كل نود تحتوي على عدة خانات

مع اعادة تعريف الإشارات و اتباع قواعد معينة و سيساعدك

هذا النوع من الإنتجر 8 byte .

__int64

و بالنسبة للنقاط انا غير معني فيها ولكن الأهم ان تستفيد و تجد ما تبحث عنه .

تم تعديل هذه المشاركة بواسطة montaser00 في 10 يوليو 2012 في 22:12

#11

@Mr.B

اقتباس
ماعلاقة الكلام الذي ذكرته بإستنتاجك الأخير؟

علاقة وطيدة ..

ذكرتُ تعريف المكدس و قلتُ أنه يتم تحديد المساحة التى سيتم حجزها به وقت ترجمة البرنامج و أن المكدس مُخصص لحجز المساحات الصغيرة ...

لذا ليس من المنطقي أن نحجز مساحة 1 غيغا من Stack .. و إلا فمالفائدة من الــ Heap ؟

هل عندك سؤال آخر ؟؟

أرجو أن لا تعطيني سالب آخر على هذه المشاركة ! (إذا كنتَ ترى أنها ليست مفيدة فغيرك يرى عكس ذلك ..)

2
#12

أغلب المصرفات تتيح لك زيادة حجم المكدس, وهذا فعلياً ماذكرة الأخ خالد في رده. في هذا البرنامج مصفوفة حجمها 1 جيجا :

#include<stdio.h>
#define SIZE 1073741824

int main(void) {

    char foo[SIZE];
    int i;

    for(i = 0 ; i < SIZE ; i++)
        foo  = 'A';
    foo[SIZE]   = '\0';

    printf("%s\n", foo);

    return(0);
}

كل مايلزم كي يعمل بدون خلل أن أزيد حجم المكدس, وسأضعه 1.2 قيقا :

C:\Users\X\Desktop>"C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\vsvars32.bat"Setting environment for using Microsoft Visual Studio 2005 x86 tools.
C:\Users\X\Desktop>cl /F 1288490190 foo.c
Microsoft ® 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright © Microsoft Corporation.  All rights reserved.
foo.c
Microsoft ® Incremental Linker Version 8.00.50727.42
Copyright © Microsoft Corporation.  All rights reserved.
/out:foo.exe
/stack:1288490190
foo.obj
C:\Users\X\Desktop>

وسيعمل البرنامج بدون مشاكل:

C:\Users\X\Desktop>foo.exeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
......
C:\Users\X\Desktop>

بغض النظر عن صحة هذه الطريقة أم لا, إلا أنها "صالحة برمجياً". وهذا يعني أن السؤال منطقي ولامشكلة به.

#13
اقتباس
هذا فعلياً ماذكرة الأخ خالد في رده

رد الأخ خالد كان واضح جدا و لا غبار عليه !, لأنه قال :

اقتباس
تذكر أن حجز كمية كبيرة من الذاكرة على الـ stack هو أسلوب خاطئ في الأصل, هي صممت لكي تكون مخزن مؤقت و سريع للدوال.

و "الأسلوب الخاطئ" أو "سوء التصميم" أو "خلل في الــ Conceptioin" .. كلها عبارات تدل على عدم منطقية البرنامج و هذا أمر لا يختلف عليه اثنان !!

اقتباس
بغض النظر عن صحة هذه الطريقة أم لا, إلا أنها "صالحة برمجياً". وهذا يعني أن السؤال منطقي ولامشكلة به.

هناك فرق شاسع بين كود "صالح برمجيا" و آخر "منطقي برمجيا" !!

عندما تحجز 1 غيغا من Stack (بغض النظر عن الطريقة المستعملة) فأنت كمن يحاول وضع اسطوانة السي دي في المكان المُخصص للبطارية !!

و ليكن في حسبانك أن "نجاحك في تنفيذ الكود لا يعني أنك على الطريق الصحيح .."

#14
bool i;
bool* g = &i;

اظن ان هذا يكفي لحجز مساحة في الذاكرة

وللحصول الى العنص المليار مما حجز للبرنامج في الرام اكتب

*( g + 1000000000 ) = 'a';

تم تعديل هذه المشاركة بواسطة nadir02 في 11 يوليو 2012 في 14:07

#15

أستاذي السيد B :

في الواقع هذا الجواب الذي كنت أنتظره تماماً ... أشكرك شكراً جزيلاً .. حصلت على الإجابة المنتظرة ... جزاك الله خيراً...

أخي نادر :

*( g + 1000000000 ) = 'a';

لم أجرب هذا .. ولكن حسب تجاربي السابقة فهذا سيؤدي إلى توقف البرنامج وإعطاء الخطأ Access Violation

على أي حال شكرا لإجابتك ...

انتهى ترشيح الإجابات ...أشكركم جزيلاً ...

لا إله إلا الله محمد رسول الله...

تمت الإجابة

والسلام عليكم ورحمة الله وبركاته ..

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 11 يوليو 2012 في 19:28

هذا الموضوع مغلق.

مواضيع مشابهة