Массив сегментов стека C - PullRequest
       2

Массив сегментов стека C

0 голосов
/ 20 февраля 2019

Я натолкнулся на пример на странице, где описываются различные способы представления строки в структурах Си.Это объясняет, что массив, определенный в функции вне main, будет храниться в сегменте стека и как таковой не обязательно будет присутствовать после его возврата, потенциально вызывая ошибку времени выполнения.

ВЫДЕЛЕННЫЙ ВОЗМОЖНЫЙ ДУБЛИКАТ ОБЪЯСНЕНО, ПОЧЕМУ Массив не удалось вернуть, т.е. указатель на элемент 0 не возвращен, он недействителен, но не показал, что причина изменения этого класса не указанаОни пропускают значение, которое выживает после удаления стекового фрейма

"приведенная ниже программа может распечатать некоторые ненужные данные, так как строка хранится в стековом фрейме функции getString (), и данные могут отсутствовать после getString() возвращает. "

char *getString() 
{ 
  char str[] = "GfG"; /* Stored in stack segment */

  /* Problem: string may not be present after getSting() returns */
  return str;  
}      
int main() 
{ 
  printf("%s", getString());   
  getchar(); 
  return 0; 
} 

Я понимаю, что другие локальные переменные C также будут определены в их соответствующих кадрах стека, и, очевидно, они могут быть возвращены, так почему это проблема для массивов?

Спасибо

Ответы [ 3 ]

0 голосов
/ 20 февраля 2019

Это должно примерно объяснить, что произошло, после возврата из getString () его стек больше недействителен.

         ^            ^ 
         |  not valid |    ^            ^
         +------------+    | not valid  |
  str--> | "GfG"      |    | not valid  | <---+
         |  ---       |    | not valid  |     |
         | stack of   |    +------------+     |
         | getString  |    | return(str)| ----+
         +------------+    | ---        |
         |            |    |            |
         | stack of   |    | stack of   |
         | main()     |    | main()     |
         +------------+    +------------+

Если скомпилирован с помощью gcc -W -Wall (всегда должны использовать эти опции), ондолжен дать предупреждение:

warning: function returns address of local variable [-Wreturn-local-addr]
0 голосов
/ 20 февраля 2019

Существует 2 ситуации:

  1. Когда вы возвращаете простое значение, например int или char, из локальной функции, и эта переменная определяется / объявляется в этой локальной функции,Это происходит успешно, потому что при возврате значение фактически скопировано .

  2. Теперь у вас есть строка "GfG" в str, а когда вы делаете return str,Копируемое значение - это то, что есть в str, и это адрес расположения массива.Таким образом, в этом случае местоположение массива (указатель) копируется, а содержимое этого массива исчезает (поскольку содержимое находилось в фрейме локального стека).

0 голосов
/ 20 февраля 2019

Разница заключается в возврате значения, а не в возврате указателя.

Когда вы делаете это:

int f()
{
    int x = 9;
    return x;
}

int main()
{
    int a = f();
    printf("a=%d\n", a);
    return;
}

Это допустимо, потому что x выходит за рамкикогда возвращается f, возвращается значение , сохраненное в x (в данном случае 9).Это значение затем присваивается a и затем печатается.

В вашем примере вы возвращаете массив.В большинстве случаев массив, используемый в выражении, превращается в указатель на его первый элемент.Так что return str совпадает с return &str[0].Это значение указателя возвращается и передается в printf.Затем printf попытался разыменовать этот указатель, но память, на которую он указывает (массив str), больше не действительна.

Таким образом, вы можете возвращать значения из функции, но если это значение является указателемк локальной переменной это не будет действительным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...