Loading...
itonev avatar itonev 22 Точки

{HOMEWORK]Как така работи ?

Здравейте :)

Пиша си аз пета задача със следния код. Очаквах да има проблем с върнатия указател към  локланата променлива на функцията обаче си работи нормално независмо, че не е  safe :)

/* 
 * File:   create_new_int.c
 * Author: mdv
 *Write a function that declares and initializes and integer on the stack, then returning it. Try creating the function
with two different declarations:
 * Created on October 26, 2015, 7:48 PM
 */

#include <stdio.h>

int new_integer();
int* new_integer_ptr();

int main() {
    int good_var = new_integer();
    printf("Good var is %d\n",good_var);
    int* bad_var = new_integer_ptr();
    printf("Bad var is %d\n",(*bad_var));
    return 0;
}

int new_integer() {
    int stack_var = 1000;
    return stack_var; // here I return copy of local stack var; It's safe
    // Now original stack_var is dead
} 

int* new_integer_ptr() {
    int  stack_var = 1000;
    int* stack_ptr = &stack_var;
    return stack_ptr; // Really bad ! Because now stack_var wil be dead so stack_ptr points to garbage 
    //It's NOT safe
}

 

Output-ът е 


Good var is 1000
Bad var is 1000


RUN FINISHED; exit value 0; real time: 0ms; user: 0ms; system: 0ms

 

Тагове:
0
C Programming
Filkolev avatar Filkolev 4482 Точки

Това според мен е синдромът "до вчера работеше". Всичко опира до това дали паметта, която е маркирана като свободна, е вече взета за други цели. Ти ползваш пойнтъра веднага след извикването на функцията и е нормално на първо време да няма проблеми, но нямаш гаранции, че такива няма да се появят на по-късен етап от изпълнението.

2
a_rusenov avatar a_rusenov 1103 Точки

В допълнение на казаното: преди връщането стекът ти изглежда по следния начин:

|                              |

|  new_integer_ptr  |      <  -  -   result

|          main             |    

----------------------------

При връщане на резултат new_integer_ptr() се премахва от стека, но въпреки това паметта, която е заемала фунцията, не се затрива - просто вече е невалидна. Върнатият указател обаче продължава да сочи към тази памет и затова програмата се изпълнява правилно.

Пробвай обаче преди да принтираш резултата, да извикаш printf() или някоя фукнция за нещо друго и виж какво ще стане. :)

1
26/10/2015 21:48:56
trismagis avatar trismagis 0 Точки

а пък според мен return stack_ptr; дереференцира пойнтера преди да го върне, т.е връща копие на съдържанието. За разлика от това:

int* new_integer_ptr() {
    int  stack_var = 1000;
    int* stack_ptr = &stack_var;
    return &stack_ptr;
}

Както и това:

int* new_integer_ptr() {
    int  stack_var = 1000;
    int* stack_ptr = &stack_var;
    return &stack_var; 
}

И в двата случая дава warning: function returns address of local variable, а в оригиналния ти код -не

0
Filkolev avatar Filkolev 4482 Точки

Дереференцирането става в main функцията. Защо мислиш, че това се случва при return? Няма логика. Функцията е дефинирана да връща пойнтър и точно това прави. Предупрежденията, които посочваш, вероятно се появяват защото директно връщаш адрес и компилаторът е достатъчно умен, за да го види.

0
trismagis avatar trismagis 0 Точки

Прави сте, сори за глупостта която казах - тествах, наистина остава поинтер и  ако си направиш watch на пойнтера, той става out of scope като се върне в main. Дори успях да я счупя:

#include <stdio.h>
int new_integer();
int* new_integer_ptr();


int main() {

    int good_var = new_integer();

    printf("Good var is %d\n",good_var);

    int* bad_var = new_integer_ptr();
    
    long double test[10000];      //nuke the stack
    memset(test, 0, sizeof(test));
        
    printf("Bad var is %d\n",(*bad_var));

    return 0;

}

int new_integer() {

    int stack_var = 1000;

    return stack_var; // here I return copy of local stack var; It's safe

    // Now original stack_var is dead

} 


int* new_integer_ptr() {

    int  stack_var = 1000;

    int* stack_ptr = &stack_var;

    return stack_ptr; // Really bad ! Because now stack_var wil be dead so stack_ptr points to garbage 

    //It's NOT safe

}

Нещата, мисля, са ясни

0
itonev avatar itonev 22 Точки

О, аз съм наясно, че това няма как да работи.

В крайна сметка извъртях един цикъл с извиквания на  printf и се счупи.

Всъщност @а_rusenov ми даде отговора, който търсех.

Счупване със сигурност ще се случи, когато имаме друг код изменящ стека.

Най-сетне се счупи с това:

for(int i=0;i<5;i++) {
        printf("Get Value # >>",i);
        scanf("%d", &value);
        printf("%d\n",value);
    }
    printf("Bad var is %d\n",(*bad_var));

 

0
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.