|
|
This article is available in: Arabic |
المؤلف Lorne Bailey <sherm_pbody(at)yahoo.com> نبذة عن الكاتب: Lorneيعيش في شيكاغو و يعمل مستشارا مختصا في Oracle و يحضر شهادة الماجستير. ترجمه إلى العربية: yacine laalaoui <yacine.laalaoui(at)caramail.com> الفهرس: |
نبذة مختصرة:
هذا المقال يعرفك على أساسيات لغة البرمجة C و كيفية
استعمال المصرفcompilerGCC، نحن على ثقة أننا سنجعلك تستطيع أن
تنفذ المصرف بأمر على السطر لبرنامج بسيط بلغة C و بعد ذلك
سنرى ما يجري حاليا و كيف تستطيع مراقبة تصريف برامجك، و كذلك نظرة أخرى على الفلي
-debugger-
لا تستطيع أن تتخيل تصريف برامج حرة بمصرف ذي مصدر مغلق، مصرف خاص؟ و كيف تطلع على ما يجري في برنامجك المنفذ؟ قد يحتوي على أبوابا خلفيةback door أو حصان طروادة Trojan. السيد Ken Thompso أحد أشهر الهاكر كتب مصرفا يترك خلفه أبوابا في برنامج الدخول 'login'، و يخلق حصان طروادة حينما يصرف المصرف نفسه. طالع وصفه في .
لحسن الحظ لدينا GCC، عندما
تنفذ configure; make; make install فإن gcc يعمل
بجد خلف الستار. كيف تجعل gcc
يعمل لصالحك، سنبدأ بتأليف برنامج للعب الورق شيئا فشيئا لنبرز وظائف المصرف، سنبدا
من خط الانطلاق أي من تنفيذ التصريف إلى إنشاء برنامج قابل للتنفيذ، و
نعبر المراجل التي يأخذها برنامج بلغة C و مختلف الخيارات
المستعملة في الأمر gcc، هذه المراحل هي التصريف الأولي
gcc -E
Pre-compile ثم التصريفCompile
gcc ثم التجميع as Assembly ثم الربط Link ld
.
أولا سنتعلم تنفيذ المصرف، لذا نكتب البرنامج الذي يعرض على الشاشة ترحيبا.
#include <stdio.h> int main()
{ printf("Hello World!\n"); }
احفظه باسم game.c ثم صرّفه بـ:
gcc game.c
المصرف يصنع برنامجا منفذا يسميه تلقائيا a.out يمكنك تنفيذه بالأمر :
a.out Hello Worldكلما صرفنا برنامجا ينتج ملف a.out يعوض البرامج السالفة. فإن أردت تسمية البرنامج القابل للتنفيذ باسم آخر غيّر الاسم التلقائي، عليك إضافة الخيار -o مرفقا باسم الملف الناتج و لنسمه game مثلا. سمه ما تشاء فالمصرف لا يفرض تسمية معينة.
gcc -o game game.c
game Hello World
سنزيد في البرنامج شيئا فشيئا و ننفذه في كل مرة، تذكر أنّ البرنامج يكتب شيئا فشيئا، لأننا لا يمكن أن نكتب برنامجا طويلا جدا لصعوبة تنقيحه و تعديله، بل نعمل شيئا فشيئا. هكذا يجب العمل.
بعدها سنصنع ملفا رأسيا يحتوي تعريف المتغيرات و الإجراءات و الوظائف و ما تحتاجه من أشياء
#ifndef DECK_H #define DECK_H #define DECKSIZE 52 typedef struct deck_t { int card[DECKSIZE]; /* number of cards used */ int dealt; }deck_t; #endif /* DECK_H */
احفظ هذا الملف باسم deck.h، بعد ذلك نعدل ملف
game.c ، فاكتب في السطر الثاني
"include "deck.h، في السطر الخامس أضف deck_t
deck;، ثم صرّفه ثانية، فإذا وجدت أخطاء صححها و أعد التصريف.
gcc -o game game.c
كيف يتعرف المصرف على نوع
deck_t؟ في مرحلة التصريف الأولي يدرج المصرف الملف
"deck.h"في
الملف
game.c جراء التوجيهة التي تلي #.
نفذ التصريف الأولي بـالخيار
-E في أمر gcc .
gcc -E -o game_precompile.txt game.c wc -l game_precompile.txt 3199 game_precompile.txtلاحظ أن الملف game_precompile.txt الناتج من التصريف الأولي فيه 3200 سطرا جاءت معظمها من الملف stdio.h .
أثناء التصريف الأولي تجري العمليات :
تعريف الثوابت يمكنك من استخدام ثابت ما مثل DECKSIZE لتعويض عدد أوراق اللعب، في كامل مصدر البرنامج، فإذا ما غيرنا قيمة الثابت يتغير في كامل المصدر أثناء التصريف الأولي.هذه المرحلة لا تجرى وحدها، بل تسبق التصريف عادة تلقائيا.
يحول المصرف المصدر إلى لغة التجميع assembly، و إذا وجد أخطاء ما فإنه يتوقف ليجرد كل الأخطاء الموجودة. هذه المرحلة مرحلة فقط و ليست كل شيء كما يعتقد الكثيرون.
يتحول البرنامج من رمز تجميعي assembly code إلى رمز شيئي object code. الرمز الشيئي لا يمكن تنفيذه لكنه مرصوص بإحكام، الخيار -c يحول الملف إلى ملف شيئي لاحقته .o
gcc -c game.cفلنعد إلى مثالنا، و نضيف إليه دالة function لخلط الأوراق عشوائيا في الجدول 'drawn' الذي يمنع تكرار الأوراق.
#include <stdlib.h> #include <stdio.h> #include <time.h> #include "deck.h" static time_t seed = 0; void shuffle(deck_t *pdeck) { /* Keeps track of what numbers have been used */ int drawn[DECKSIZE] = {0}; int i; /* One time initialization of rand */ if(0 == seed) { seed = time(NULL); srand(seed); } for(i = 0; i < DECKSIZE; i++) { int value = -1; do { value = rand() % DECKSIZE; } while(drawn[value] != 0); /* mark value as used */ drawn[value] = 1; /* debug statement */ printf("%i\n", value); pdeck->card[i] = value; } pdeck->dealt = 0; return; }
احفظ الملف باسم shuffle.c، صرفه ثم نفذه ليخلط الأوراق و يعرضها أمامك بالدالة printf لنعرف ما يجري في برنامجنا، هذه الدالة تستعمل عادة للفلي ( فلى يفلي فليا= debbuge) ، الذي سنتحدث عنه لاحقا.
تذكر أمرين هامين:نفذ الأمر
gcc -c shuffle.cالذي ينتج عنه الملف shuffle.o إن لم ترتكب أخطاء في shuffle.c . حرر الملف game.c و أضف بعد السطر السابع الذي فيه تعريف المتغير deck لسطر الآتي:
shuffle(&deck);
أعد صنع البرنامج القابل للتنفيذ، انتبه فالبرنامج به أخطاء
gcc -o game game.c /tmp/ccmiHnJX.o: In function `main': /tmp/ccmiHnJX.o(.text+0xf): undefined reference to `shuffle' collect2: ld returned 1 exit status
آخر مرحلة هي الربط، أي جعل البرنامج قابلا للتنفيذ بالأمر :
gcc -o game game.o shuffle.oإذ يحول الأجزاء الشيئية إلى برنامج قابل للتنفيذ. إذ تتلاحم الملفات الشيئية shuffle.o و game.o بعبارة أخرى ربط الإجراءات الموجودة في الملفات الرأسية بما هو موجود في الملف الرئيسي main مثل shuffle مع deck.h أو printf مع stdio.h .
الخيار -Wall يعرض كل الأخطاء و التنبيهات في برنامجك مما يجعله محمولا قدر
الإمكان، فإذا نفذته على برنامجنا ظهر لك :
game.c:9: warning: implicit declaration of function `shuffle'
void shuffle(deck_t *pdeck);
خيار آخر يستعمل لتحسين جودة البرنامج القابل للتنفيذ ( جعله أمثل optimization) هو الخيار -#O مثل -O2 الذي يجعل البرنامج أسرع، لن تلاحظ شيئا، لكن البرامج الكبيرة جدا تبدو أسرع بعد تحسينها، الرقم 2 أو غيره يحدد مستوى التحسين..
برنامجنا يعمل جيدا، و نستطيع عرض نتائجه بـ
game | sort - n | lessلكن ما عسانا نفعل إن لم يكن كذلك، كيف يمكننا تدقيق برنامجنا لاستكشاف الأخطاء؟
يمكنك تفحص البرنامج بفليه بالمفلاة ( أداة للفلي) إما gdb على سطر الأوامر أو KDbg على الواجهة الرسومية. إذا استعملت Kdbg اختر البرنامج القابل للتنفيذ من اللائحة file->executable ، ثم اضغط F5 أو اختر القائمة File->Run فترى النتائج في نافذة على حدى ، و إلا عليك إعادة التصريف بالأمر :
gcc -g -c shuffle.c game.c gcc -g -o game game.o shuffle.o
الفلي مهم جدا لذا خصص وقتا لتعلم استعمال Kdbg و gdb لاستكشاف الأخطاء و ما أحوجك لذلك، و يمكنك تحديد نقاط لتوقيف التنفيذ، بأن تنقر بزر الفأرة الأيسر على السطر الذي به الدالة shuffle فتظهر لك نقطة حمراء صغيرة بعد هذا السطر، اضغط الزر F5 فيتوقف التنفيذ عند هذه النقطة بالذات، و بالضغط على F8 ستدقق ما يجري داخل الدالة shuffle، و إذا وضعت مؤشر الفأرة على متغير ما ترى قيمته الحالية.
يحتوي هذا المقال على كيفية تصريف برنامج C و فليه مرورا بكل مراحل التصريف بـ gcc . لإنشاء برنامج منفذ و التي منها مرحلة الربط ( النهائية)، فمن خلال هذا نأمل أن تستطيع تبدأ البرمجة بلغة C و استعمال المصرف gcc و الفلي مثل Kdbg و gdb.
و هناط أيضا مصادر أخرى للمعلومات كالأمر man و على الصفحات info حول المصرف gcc أو ld.
|
الصفحات برعاية طاقم لينكس فوكُس
© Lorne Bailey, FDL LinuxFocus.org اضغط هنا للتنبيه عن خطأ أو لارسال ملاحظاتك إلى لينكس فوكُس |
معلومات عن الترجمة:
|
2002-05-09, generated by lfparser version 2.27