Несколько вопросов по указателям в С++

102
01 мая 2021, 00:30

Возникло несколько вопросов связанных с raw pointers в С++. Рассмотрим следующий код

#include <stdio.h>
struct Point {
    double x, y;
};
int main(void) {
    Point* p = new Point;
    delete p;
    /* 
    * Далее выполняется очень большое кол-во разных
    * действий связанных с созданием разных объектов,
    * включая Point, а также их удалением.
    */
    printf("address = %d, x = %f", p, p->x); //строчка X.
    return 0;
}

Вопросы:

  1. Для очередного создаваемого объекта Point выделился как раз тот участок памяти, на который указывает указатель p. Возможно ли такое совпадение? Если да - выполнится ли строчка Х успешно?

  2. Для очередного создаваемого объекта НЕ ТИПА POINT выделился участок памяти, на начало которого как раз указывает указатель p. Объект представлен структурой с тремя полями double. Возможно ли такое? Если да - выполнится ли строчка Х успешно?

  3. Участок памяти выделенный под объект Point после его освобождения был передан ОС, а затем стал частью другого процесса. Возможно ли такая ситуация? Если да - чисто теоретически, возможно ли через указатель p обратиться к данным другого процесса?

Answer 1

Так если мне ничего не мешает обратится к полю x структуры такого же типа, расположенной по адресу хранимому в указателе p - как сценарий в строке Х может не выполнится?

Строка Х выполнится, но результат выполнения непредсказуем и может быть ошибочным всегда или иногда. Или даже результат всегда будет не то чтобы правильным, но ожидаемым человеком, который написал этот ошибочный код.

Такой код, какой приведен в вопросе это ошибочный код. Он скомпилируется, но будет работать с ошибкой (возможно, что ошибка будет проявляться иногда, а возможно и никогда, если соответствующий компилятор расположит структуры данных удачным образом). В языке С++ нет защиты от таких ошибок на уровне языка. За это (за отсутствие защиты от таких ошибок) язык С++ многие критикуют. Зато язык С++ позволяет писать более эффективные программы, если программист сам контролирует такие потенциально ошибочные моменты.

Answer 2

Начнем с того, что это не C, а С++.

1,2. После delete p; память, на которую указывает p, свободна, так что она может быть аллоцирована под что угодно (если позволяет объем соответствующего непрерывного куска свободной памяти). Так что описанное вами вполне возможно. О строке x см. далее.

  1. Нет, это адресное пространство, выделенное процессу. Вы просто получите, обращаясь по указателю, память по которому освобождена, undefined behaviour.

Строчка x полукорректна :) - адрес вы можете вывести в любом случае - просто как содержимое переменной p, что еще не означает его корректности, что к нему можно обращаться. Обращение p->x работает только в том случае, если вы обращаетесь к корректно выделенной и не освобожденной памяти (или к адресу переменной - типа

Point pp;
p = &pp;

). После delete p; это становится UB (понятно, что после p = &pp; само освобождение delete p; является UB).

Если между удалением и выводом у вас вновь выполнено присвоение p указателя на выделенную память или адреса объекта Point - то строка x корректна.

Вкратце так. Можно расписывать и более подробно, но...

READ ALSO
Чем открыть проект .cbproj?

Чем открыть проект .cbproj?

Достался проект с расширениемcbproj

105
Ключевое слово this с++

Ключевое слово this с++

Возник такой вопросВ коде реализуется конструктор копирования обьекта

120
Как подключить библиотеку sfeMovie?

Как подключить библиотеку sfeMovie?

Я хочу подключить библиотеку sfeMovie (для отображения видео) к проектуДелаю всё по инструкции: http://sfemovie

107