Russian Qt Forum

Программирование => С/C++ => Тема начата: artur567297@gmail.com от Июнь 27, 2022, 01:00



Название: есть в С++ стандартная функция проверки валидности указателя?
Отправлено: artur567297@gmail.com от Июнь 27, 2022, 01:00
Здравствуйте. Помогите новичку с проверкой указателя перед удалением.
Недавно начал заниматься с++ и такая проблема:
Создал простой класс он содержит указатель char* buffer, конструктор и деструктор, и больше не чего вот его код: 
class MyStringDefaultCopy
{
 
private:
    char* buffer;
MyStringDefaultCopy(const char* initString) // Constructor
    {
       buffer = new char[strlen(initString) + 1];
       strcpy(buffer, initString); 
    }

~MyStringDefaultCopy() // Destructor
    {
        delete[] buffer;
        *buffer = NULL;     
    }
}
Создал одну простую функцию:
void UseMyString(MyStringDefaultCopy str)
{
    cout << "вызов функции UseMyString  " << endl;
}
Код Main простой состоит из двух строк:
MyStringDefaultCopy sayHello("Hello");
UseMyString(sayHello);
ПРОБЛЕМА: Код Main отрабатывает но по завершении программы выдает ошибку _CrtIsValidHeapPointer. Я знаю из за чего возникает эта ошибка: проблема вот в чем в коде Main при вызове функции UseMyString передается копия объекта sayHello, которая соответственно в конце функции уничтожается. Так как у объекта sayHello есть указатель и деструктор но нет копирующего конструктора, по этому при создании копии для функции UseMyString используется копирующий конструктор по умолчанию который просто скопирует все указатели в классе, соответственно после выполнения функции UseMyString удаляется копия MyStringDefaultCopy str и вызывается деструктор который делает указатель buffer неопределенным. При окончании Main удаляется уже основной объект sayHello и вызывается его деструктор который указатель buffer уже удалить не может так как он не определен. Собственно вопрос есть метод проверки валидности указателя перед его удалением: типа *buffer = NULL – не помогает. Можно присвоить после удаления указателю значение, например *buffer = “удален” и перед удалением сравнивать на это значение но может есть стандартная функция проверки валидности указателя?   


Название: Re: есть в С++ стандартная функция проверки валидности указателя?
Отправлено: kambala от Июнь 27, 2022, 10:21
Цитировать
Я знаю из за чего возникает эта ошибка
все верно

валидность голого указателя проверить нельзя, присваивать специальное значение — тоже плохое решение. но в данном случае есть решение намного проще: сделать параметр функции константной ссылкой, тогда копия объекта создаваться не будет.

голыми указателями для управления памятью вообще пользоваться очень не рекомендуется чтобы избежать огромного слоя ошибок, для этого давно придумали «умные» указатели (std::unique_ptr, std::shared_ptr).

кстати, выражение *buffer = NULL; в данном случае ошибочное, т.к. разыменовывается «мусорный» указатель.

P.S. для оформления кода есть специальный тэг: [ code=cpp]код [ /code] (только пробелы после [ убрать)


Название: Re: есть в С++ стандартная функция проверки валидности указателя?
Отправлено: artur567297@gmail.com от Июнь 27, 2022, 14:34
спасибо


Название: Re: есть в С++ стандартная функция проверки валидности указателя?
Отправлено: sergek от Июнь 27, 2022, 15:07
Собственно вопрос есть метод проверки валидности указателя перед его удалением: типа *buffer = NULL – не помогает. Можно присвоить после удаления указателю значение, например *buffer = “удален” и перед удалением сравнивать на это значение но может есть стандартная функция проверки валидности указателя?   
Вы путаете указатель и область памяти, на который этот указатель "указывает", что вам уже и подсказали. Можно buffer = nullptr, но это не решает вашу, надо отметить, надуманную проблему. Используйте конструктор копирования, в котором для копии распределяется своя память и переносится содержимое из копируемого объекта.


Название: Re: есть в С++ стандартная функция проверки валидности указателя?
Отправлено: juvf от Январь 23, 2023, 10:33
Собственно вопрос есть метод проверки валидности указателя перед его удалением: типа *buffer = NULL – не помогает. Можно присвоить после удаления указателю значение, например *buffer = “удален” и перед удалением сравнивать на это значение но может есть стандартная функция проверки валидности указателя?   

Код:
~MyStringDefaultCopy() // Destructor
    {
        delete[] buffer;
        buffer = 0; //или buffer  = NULL; без разименования *buffer = NULL
    }
вызов деструктора по нулевому указателю разрешенная в с++ операция. "delete 0;" - операция ни чего не делает и безопасная.