В следующем фрагменте кода str_s не должен указывать на какое-то место в стеке.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* fun_s(){
char str[8]="vikash";
printf("s :%p\n", str);
return str;
}
char* fun_h(){
char* str = (char*)malloc(8);
printf("h :%p\n", str);
strcpy(str, "vikash");
return str;
}
int main(){
char* str_s = fun_s();
char* str_h = fun_h();
printf("s :%p\nh :%p\n", str_s, str_h);
return 0;
}
Я понимаю, что существует проблема с возвратом fun_s, и содержимому этого указателя нельзя доверять, но, насколько я понимаю, он должен указывать на какое-то место в стеке, а не на ноль? Я получаю следующий вывод в моей консоли. Можете ли вы объяснить, почему печать третьей строки (ноль) не 0x7ffce7561220
s :0x7ffce7561220
h :0x55c49538d670
s :(nil)
h :0x55c49538d670
Версия GCC
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ОС: Ubuntu 18.04.3 LTS
2 ответа
Ваш компилятор специально вводит нулевое возвращаемое значение из этой функции. У меня нет доступного gcc 7.4, но у меня есть 7.3, и я предполагаю, что результат похож:
Компиляция fun_s
в сборку обеспечивает это:
.LC0:
.string "s :%p\n"
fun_s:
push rbp
mov rbp, rsp
sub rsp, 16
movabs rax, 114844764957046
mov QWORD PTR [rbp-8], rax
lea rax, [rbp-8]
mov rsi, rax
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, 0 ; ======= HERE =========
leave
ret
Обратите внимание на жесткий набор от нуля до eax, который будет содержать результирующий указатель при возврате к вызывающей стороне.
Создание str
статического дает следующее:
.LC0:
.string "s :%p\n"
fun_s:
push rbp
mov rbp, rsp
mov esi, OFFSET FLAT:str.2943
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
mov eax, OFFSET FLAT:str.2943
pop rbp
ret
Короче говоря, ваш компилятор обнаруживает возвращение локального адреса и переписывает его как NULL. При этом он предотвращает любое последующее злонамеренное использование указанного адреса (например, атака внедрения контента).
Я не вижу причин, по которым компилятор не должен это делать. Я уверен, что сторонник языковой чистоты подтвердит или опровергнет это подозрение.
Большинство современных компиляторов обнаруживают возвращение указателя на локальную переменную и фактически возвращают NULL (вообще говоря, они более агрессивны в отношении UB, и подход таков: пусть программа завершится неудачно как можно скорее или «сделает UB возможным для обнаружения времени выполнения», как в данном случае) https://godbolt.org/z/pDUXmm
Похожие вопросы
Связанные вопросы
Новые вопросы
c
C - это язык программирования общего назначения, используемый для системного программирования (ОС и встраиваемых), библиотек, игр и кроссплатформенности. Этот тег следует использовать с общими вопросами, касающимися языка C, как это определено в стандарте ISO 9899 (последняя версия 9899: 2018, если не указано иное, а также для запросов, специфичных для версии, с c89, c99, c11 и т. Д.). C отличается от C ++ и не должен сочетаться с тэгом C ++ без разумной причины.