Да, я прекрасно знаю, что тебе не следует этого делать. Если у нас есть этот код:
int *foo() {
int a = 42;
return &a;
}
Как известно большинству кодеров C, это поведение undefined: Использование указателя после free()
int *p = foo();
printf("%d\n", *p);
Просто чтобы будущие читатели не приняли это за правду. Все нижеизложенное до вопроса было основано на ложном предположении от меня. Это не УБ. Это просто плохо.
Как некоторые кодеры C знают, но меньше, чем выше, что это также UB, хотя разыменование не выполняется: (пытался найти хороший вопрос об этом, но никого не нашел)
int *p = foo();
printf("%p\n", p); // Should be printf("%p\n", (void*) p);
// Eric P clarified this in his answer, but this missing cast
// is not a part of the primary question
И по той же причине это тоже UB, потому что происходит то, что указатель становится неопределенным, как неинициализированная переменная. Так называемый висячий указатель.
int *p = foo();
int *q = p;
И несколько удивительно для некоторых, даже это не нормально:
free(ptr);
if(ptr == NULL) // Just as bad as if ptr is not initialized
Вопрос
Что мне интересно, так это то, что эта единственная строка вызывает UB:
int *p = foo();
Или, может быть, даже это?
foo();
Другими словами, p
становится висячим указателем или он назначается висячему указателю?
Я не знаю, есть ли в этом какая-то практическая польза, кроме более глубокого понимания языка Си. Одним из хороших вариантов использования было бы выяснить, какие рефакторинги срочные, а какие могут подождать.
int *p = foo();
не является UB, как и последующийprintf("%p\n", p);
. Этот указатель будет иметь значение (адрес), и этот адрес можно будет распечатать. Только когда вы пытаетесь разыменовать его, срабатывает UB. - person Adrian Mole   schedule 12.03.2021p
не имеет практического применения, которое не вызовет НБ. - person Eugene Sh.   schedule 12.03.2021p
на объект? Разве не&a
становится неопределенным перед присваиванием? - person klutt   schedule 12.03.2021free
не только освобождал память для объекта, но также освобождал или изменял память, используемую для вспомогательных данных. Эти данные могут понадобиться для использования значения указателя, даже для его печати. - person Eric Postpischil   schedule 12.03.2021p
делает его неопределенным само по себе? Или вы имеете в виду, что это может быть UB? - person Eugene Sh.   schedule 12.03.2021p = foo(); q = p;
вызовет UB. - person klutt   schedule 12.03.2021p
становится висячим указателем или он назначается висячему указателю? - person klutt   schedule 12.03.2021AnyType x = y;
x
неопределенным значением, еслиy
является неопределенным значением, я думаю, что сам стандарт C ничего не говорит об этом в отношении его открытого текста, но есть некоторая история в ответах на отчеты о дефектах комитета C и другие заявления, которые это делаетx
неопределенным. Это основано на воспоминаниях о предыдущих обсуждениях Stack Overflow; Я не ожидал, что смогу найти его в отчетах о дефектах или в комментариях Stack Overflow. - person Eric Postpischil   schedule 12.03.2021int *p = foo(); printf("%p\n", p);
имеет 2) присвоение неопределенного указателя, 2.5) возможное преобразование сомнительного указателя вvoid *
3) передачу сомнительного указателя вprintf()
и 4) печать сомнительного указателя. klutt, Вы ищете UB в любом из этих шагов? - person chux - Reinstate Monica   schedule 13.03.2021