2013-07-02 3 views
0

Я читал эту статью (http://www.codeproject.com/Articles/627/A-Beginner-s-Guide-to-Pointers), в которой есть код, объясняющий причину, по которой мы должны их использовать. например. Динамическое распределение.Указатели - Динамическое распределение путаницы

Eg.1. Неправильная программа:..


«Эта программа в первую очередь вызывает функцию SomeFunction, которая создает переменную с именем nNumber, а затем делает точку pPointer к нему тогда, однако, где проблема Когда функция уходит, nNumber удаляется, потому что это локальная переменная. Локальные переменные всегда удаляются, когда выполнение оставляет блок, в котором они были определены. Это означает, что когда SomeFunction возвращается к main(), переменная удаляется. Таким образом, pPointer указывает, где используется переменная быть, который больше не принадлежит этой программе ».

#include <stdio.h> 

int *pPointer; 

void SomeFunction() 
{ 
    int nNumber; 
    nNumber = 25;  

    // make pPointer point to nNumber: 
    pPointer = &nNumber; 
} 

void main() 
{ 
    SomeFunction(); // make pPointer point to something 

    // why does this fail? 
    printf("Value of *pPointer: %d\n", *pPointer); 
} 

Eg.2. Правильная программа:


«Когда SomeFunction называется, он выделяет некоторую память и делает pPointer точку к нему на этот раз, когда функция возвращает, новая память остается нетронутой, поэтому pPointer все еще указывает на что-то полезное. Это для динамического распределения! "

#include <stdio.h> 

int *pPointer; 

void SomeFunction() 
{ 
    // make pPointer point to a new integer 
    pPointer = new int; 
    *pPointer = 25; 
} 

void main() 
{ 
    SomeFunction(); // make pPointer point to something 
    printf("Value of *pPointer: %d\n", *pPointer); 
} 

Мой вопрос:


Это выше объяснений сделал полный смысл для меня, и я чувствовал себя хорошо о том, почему мы используем указатели. Затем я решил запустить программы, чтобы узнать, что произойдет. Я ожидал, что первая отобразит некоторое случайное число для * pPointer, потому что 25 были удалены. Обе программы отображают «Значение * pPointer: 25» правильно. Должна ли первая программа не сработала, как сказано в учебнике?

+0

Возможный дубликат [Возврат адреса локального или временная переменная] (http://stackoverflow.com/questions/2744264/returning-the-address-of-local-or-temporary-variable) – Lstor

+0

Это приятное объяснение: http://stackoverflow.com/questions/ 6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794 # 6445794 – Lstor

ответ

3

Это потому, что это undefined поведение. Вам просто повезло, что функция printf не написана над этим местоположением.

вещь (если я могу быть ироничной) о неопределенном поведении, заключается в том, что она не определена, вы не можете сказать, что произойдет раньше. Также см. nasal demons.

+0

технически, pPointer будет разыменован до того, как будет выполнен printf(), поэтому, по крайней мере, он надежный! – user1158559

+0

@ user1158559 Ах да, это правильно, поэтому он «работает». –

0

Обе программы отображают «Значение * pPointer: 25» правильно. Не должно первая программа потерпела неудачу, поскольку в учебнике говорилось, что это будет?

В первой программе nNumber находится в стеке. Когда SomeFunction() выходит, nNumber «выходит из сферы действия», что означает, что он больше не существует с точки зрения программы. Однако память, которая использовалась для этой переменной, все еще существует, и она будет содержать то же значение, что и при nNumber, пока не будет записано какое-то новое значение. pPointer продолжает указывать на это место, конечно, чтобы вы могли смотреть на ценность этой памяти. По мере выполнения других функций эта память в конечном итоге будет использоваться для некоторой новой переменной, и значение изменится. Опасность состоит в том, что если вы продолжаете использовать pPointer, ожидая, что он останется в силе, вы обнаружите, что значение, которое оно указывает на постоянное изменение.

0

То, что не определено поведение.Нет никакой проверки на то, чтобы указатель, который был удален, указывал на действительное значение или нет. Проверьте this удивительный ответ здесь.

Короче говоря,

Когда переменная выходит из области видимости, все возможно в том месте, где переменная была ранее сохраненным (даже после того, как вы delete, delete просто освобождает память, оно не обязательно протирать его) ,

Это может быть переписано уже, возможно, находится в процессе написания или ничего не изменилось до сих пор. (например, в вашем примере). Так как в его пробеле, доступном для вашего кода, вы не найдете никаких ошибок seg и т. Д.

+0

Спасибо, ребята, я теперь понимаю, зачем в этом случае использовать указатели. – user2364266

0

Локальные переменные выделяются в стеке. Когда функция завершается, указатель на вершину стека изменяется так, что локальные переменные находятся вне стека, но стек не стирается. Следовательно, значение 25 будет по-прежнему находиться в ячейке памяти, на которую указывает pPointer. Если вы вызываете другую функцию с локальными переменными, эта память будет перезаписана.

printf() будет перезаписывать местоположение, но pPointer будет разыменован для использования в аргументе перед выполнением printf().

0

Причина, по которой работала первая программа, заключается в том, что в C++ использование указателя на уничтоженную переменную не определено. Но то, что C++ не диктует, - это то, что происходит с этой памятью. Локальные переменные выделяются с использованием так называемого Stack Frame в C++ или если вы знакомы с языком сборки «The Stack» после завершения функции часто, когда эта память фактически не уничтожена, а скорее не защищена от перезаписи. Поэтому в течение некоторого времени, когда указатель может работать, но в какой-то другой момент времени память, которую вы указываете, также может быть перезаписана.

Техническое объяснение этого явления заключается в том, что при вводе функции его адрес переносится в сегмент стека. Локальные переменные затем определяются как смещение ниже этого нажатого адреса и указателя стека. Это эффективно дает вам память в стеке для доступа к локальным переменным. Но как только функция уходит, а не тратит время на перезапись этой памяти, память остается незащищенной для чтения и записи из более поздних операций, так как такое поведение не определено, потому что мы понятия не имеем, в какой момент эта память больше не будет действительной и как долго эта память действительно не задается в камне и часто колеблется. Если вы ищете объяснение, это видео дает хороший обзор, не вдаваясь в подробности хардкора: http://www.youtube.com/watch?v=vcfQVwtoyHY.

0

В первой программе указатель по-прежнему будет указывать на место в памяти, где хранится номер 25. Это верно. Проблема заключается не столько в том, что номер 25 был перезаписан; это то, что он мог был перезаписан. Другие программы имеют бесплатную лицензию на беспорядок с этой ячейкой памяти без превышения границ с первой программой, но до тех пор, пока что-то не обернется, чтобы изменить это значение, аппаратное обеспечение все еще сохраняет номер 25.

Смежные вопросы