Код, включающий конструктор копирования по умолчанию, должен быть segfault, но работает просто отлично - PullRequest
0 голосов
/ 14 мая 2018

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

Следующий код вызывает конструктор копирования по умолчанию при вызове myFunction().Перед выходом из области действия myFunction () вызывается мой определенный пользователем ~myClass(), который должен вызывать free() на dangerData.Однако, похоже, что это не освобождает dangerData!

#include <cstdio>
#include <cstdlib>

class myClass {
    static int nextid;
    int myID;
    char *dangerData;

    public:

    myClass() {
        myID = nextid++;
        printf("Constructing myClass number %d\n", myID);
        dangerData = (char *)malloc(1024);
        dangerData[12] = 0;
    }

    ~myClass() {
        printf("Destructing myClass number %d. dangerData = %p\n", myID, (void *) dangerData);
        dangerData[12] = 'a'; //Mark the array
        free(dangerData); //This call chould free the array... but it doesn't!
    }

    void msg() {
        printf("Message from myClass number %d. dangerData[12] = %d\n", myID, dangerData[12]);
    }
};

int myClass::nextid = 1;

void myFunction(myClass param) {
    param.msg();
}

int main() {
    myClass m;
    myFunction(m); //Calls default copy constructor
    m.msg();
    return 0;
}

Выходные данные этого кода:

Constructing myClass number 1
Message from myClass number 1. dangerData[12] = 0
Destructing myClass number 1. dangerData = 02f71458. dangerData[12] = 0
Message from myClass number 1. dangerData[12] = 97
Destructing myClass number 1. dangerData = 02f71458. dangerData[12] = 97

Первый вызов дескриптора определенно вызов free() в массиве malloc, однако вызов m.msg() в main() все еще может получить к нему доступ без сегмента!

Это должно происходить?

1 Ответ

0 голосов
/ 14 мая 2018

Это должно происходить?

Здесь не должно происходить ничего "предполагаемого" или, скорее, "ожидаемого" - вы вызываете неопределенное поведение, поэтому все, что может случается, включая «ничего».

вызов функции m.msg () в main () все еще может получить к нему доступ без сегмента!

Это не ужасноУдивительно (но опять же, ни на что не стоит рассчитывать).Освобождение памяти более или менее говорит ОС, что эта память может быть свободно использована / перезаписана.Чем больше внимания уделяется скорости над безопасностью между вашим компилятором, ОС и их настройками, тем меньше усилий они потратят на то, чтобы пометить эту память как недоступную, и, поскольку вы просто использовали именно эту область памяти, вам пришлось бы выполнять очень строгие проверки ОС.чтобы даже получить segfault там.Кроме того, крайне маловероятно, что этот 13-й символ будет перезаписан во время между двумя вызовами msg(), поэтому вы, вероятно, снова будете читать то же самое.

Но все это относится только к этому небольшому примеруи, опять же, не на что полагаться.Неопределенное поведение (в некоторой степени, к сожалению) не означает автоматически, что ваша программа будет работать с ошибками сейчас.Это может произойти, или может произойти ошибка по прошествии двух минут в совершенно другой части, либо вывести на экран неверные результаты, либо отформатировать жесткий диск.Или это может работать так, как вы и планировали, на этот раз.

...