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

سؤال عن عدم إرجاع مؤشر لمتغير محلى؟

بدأه mhewedy في 11 يونيو 2010 · 8 رد · 433 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم,,

بصراحة أنا مازلت جديد في موضوع ال C (و إن كانت لدي خلفية ضئيلة من أيام الكلية), و أكثر ما يجذبني هو في ال C هو الإمكانيات التي تجعلها تتعامل مع الذاكره بمرونه

المهم, لدي سؤال:

بقرائتي للموضوع التالي قرأت التالي (او كما يقول الكاتب)

عندما تقوم بإرجاع مؤشر من دالة, تأكد أن هذا المؤشر لا يشير على متغير محلى, و لكن لابأس إن تم عمل dynamic mem allocation له.

قمت بكتابة بيرمج صغير لإختبار هذه الخاصية, و عند التنفيذ وجدت أنه لا ضير من إرجاع مؤشر على متغير داخلي (لم يشتكى أحد)

#import <stdio.h>

typedef struct{
	int id;	
}emp;

emp* function();

int main(void){

	emp* e = function();
	printf("%i\n", e->id);

	system("pause");
	return 0;	
}

emp* function(){
	 emp* ret;
	 //ret = malloc (sizeof *ret);		// correct?
	 emp local; ret = &local;		// error?
	 ret->id = 100;
	 return ret;
}

أظن المشكله بهذا السطر:

 	emp local; ret = &local;		// error?

و أنه يجب أن يستبدل بهذا السطر:

 ret = malloc (sizeof *ret);		// correct?

ولكن حال التنفذ تم التنفيذ بنجاح, هل هذا بسبب أن الذاكره لم يتم إسترجاعها بعد أم ماذا؟

نرجو الإفاده

ملاحظه, في حالة الجافا, فنحن لا نشغل بالنا بمثل هذا الكلام, حقيقة أعتقد لأنه لايوجد أصلا به إرجاع بال... (return by reference يعني :lol:)

فكل كائن يتم تخليقة داخل الدالة فهو يتم إنشاءه بطريقة Dynamic mem allocation (بإستخدام new )...

#2

لم يشتكى ولكنة سيشير لمكان خطاء فى الذاكرة وسيسبب اما نتائج غير معروفة )قد يشير الى قيمة -555 مثلا( او كراش للبرنامج .

اى متغير يتم انشائة فى دالة محلية يتم حجزة فى stack وبمجرد انتهاء الفانكشن يتم مسح الstack لذلك سيكون الموشر على متغير محلى لا يشير على المعلومات الصحيحة .

السى بعادتها لا تمنع حدوث الاخطاء من تلك النوع وخاصة اخطاء الموشرات . فهى تفترض ان المبرمج يعرف ماذا يفعل : :lol:

//بالنسبة للكود غريبة ! حاحاول اشوف اية السبب

تم تعديل هذه المشاركة بواسطة apex في 11 يونيو 2010 في 09:38

1

name : mohamedyosry

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


typedef struct{
        int id; 
}emp;

emp* function(int x );

int main(void){

        emp* e = function(1);
        function(0);
        //int x[]={0,0,0,0,0,0,0,0,0,0,0,0,0};
        printf("%i", e->id);
        return 0;       
}

emp* function(int x){
         emp* ret;
         //ret = malloc (sizeof *ret);          // correct?
         emp local; ret = &local; 
                       // error?
         if(x)              
         ret->id = 100;
         else
         ret->id = 50;
         return ret;
         }

فقط gcc لم ينظف الstack (ولكنها ستنظف بعد عدة نداهات لدوال اخرى

كود الاسمبلى

disassemble function
Dump of assembler code for function function:
0x00000000004004fb <function+0>:	push   %rbp
0x00000000004004fc <function+1>:	mov    %rsp,%rbp
0x00000000004004ff <function+4>:	lea    -0x10(%rbp),%rax
0x0000000000400503 <function+8>:	mov    %rax,-0x8(%rbp)
0x0000000000400507 <function+12>:	mov    -0x8(%rbp),%rax
0x000000000040050b <function+16>:	movl   $0x64,(%rax)
0x0000000000400511 <function+22>:	mov    -0x8(%rbp),%rax
0x0000000000400515 <function+26>:	leaveq 
0x0000000000400516 <function+27>:	retq

ل

emp* function(){
         emp* ret;
         //ret = malloc (sizeof *ret);          // correct?
         emp local;
          ret = &local;             
         ret->id = 100;
         return ret;
         }

.

تم تعديل هذه المشاركة بواسطة apex في 11 يونيو 2010 في 11:09

1

name : mohamedyosry

#4

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

السبب هو ان المتغير لم يتم حدوث overwrite له بعد ، لابد ان تعرف ان كل اجراء فرعي يتم حجز الـstack الخاص به مباشرة فوق الـstack الخاص بالاجراء الاب .

هذا رسم بسيط قمت به ربما يوضح الامر :

stackw.jpg

جرب هذا الكود وسترى الفرق :

#include <stdio.h>

typedef struct{
 	int id; 
}emp;

emp* function();

void crap()
{
 	char local[512];
 	memset(local, 0xff, 512);
}

int main(void){

 	emp* e = function();
 	crap();
 	printf("%i\n %p", e->id,e);
 	return 0; 	
}

emp* function(){
 	emp* ret;
 	//ret = malloc (sizeof *ret); 
 	// correct?
 	emp local;
 	local.id = 110;
 	printf("%p \n",&local);
 	ret = &local; 	// error?
 	printf("%p",ret);
 	return ret;
}
3

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

#5

هذا هو الناتج:

0022FF40
0022FF40
110
 0022FF40

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

أستخدم Dev-C++ مع GCC عن طريق mingw32

#6

ظبط معايا

0x7fff77f60730 
0x7fff77f60730
-1
 0x7fff77f60730

بدل

0x7fffb4a4c650 
0x7fffb4a4c650
110
 0x7fffb4a4c650

جرب تكبر حجم استخدامك لstack

مثلا

void crap()
{
        char local[2048];
        memset(local, 0xff, 2048);
}

تم تعديل هذه المشاركة بواسطة apex في 11 يونيو 2010 في 11:32

name : mohamedyosry

#7

لا السبب هو ان الـcompiler قام بعمل discard للدالة اصلا لانه يعتقد انها useless .

قم بترجمة الكود في الـdebug mode او غير الـoptimization options الى disabled .

2

mov eax, dword ptr ds:[0xffdf0308]

jmp dword ptr [eax+0xfc]

#8
اقتباس
لا السبب هو ان الـcompiler قام بعمل discard للدالة اصلا لانه يعتقد انها useless .

قم بترجمة الكود في الـdebug mode او غير الـoptimization options الى disabled

+1

على المستوى الثالث قام بذلك

gcc -O3  -o 1 1.c

name : mohamedyosry

#9

أود أن أشكر جميع من شارك في هذا الموضوع

لقد أفدتموني

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

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…