C ++ Можно ли определить, указывает ли указатель на действительный объект?

18

Я изучаю C ++ и читаю C ++ Primer. Я хотел бы узнать ответ:

Учитывая указатель p , вы можете определить, указывает ли p на действительный объект? Если да, то как? Если нет, почему бы и нет?

Спасибо.

    
задан 2013Asker 20.06.2013 в 00:40
источник

4 ответа

27

Нет, вы не можете. Зачем? Потому что было бы дорого поддерживать метаданные о том, что представляет собой действительный указатель, а что нет, а на C ++ вы не платите за то, что не хотите.

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

    
ответ дан Kerrek SB 20.06.2013 в 00:45
источник
6

Невозможно. Подумайте об этом сценарии.

int *ptr = new int(10);
int *ptrDup = ptr;

delete ptr;

Но ptrDup все еще указывает на ячейку памяти, указанную ptr , которая больше не существует. Таким образом, отсрочка ptrDup приводит к неопределенному поведению. Но есть подсчет ссылок, который является совершенно другой концепцией.

    
ответ дан Mahesh 20.06.2013 в 00:45
источник
4

Невозможно увидеть, является ли указатель «действительным» во всех его значениях.

Конечно, вы можете попытаться разыменовать указатель ( *ptr = x; или x = *ptr ). Если ваш код не сбой, указатель указывает на действительную память. Если он упал, очевидно, указатель не годится. К сожалению, этот подход немного похож на проверку того, загружена ли пушка, выстрелив в голову - что не самое умное ... К сожалению, с указателями нет «проверьте камеру, чтобы увидеть, загружена ли она», поэтому нет реального хорошего способа выяснить, является ли указатель действительным, кроме «если он не вызывает аппаратную ошибку, он действителен».

Обратите внимание, что это только на самом деле скажет вам, что «указатель указывает на некоторую память, к которой вы можете получить доступ» в большинстве случаев. Это НЕ означает, что указатель «правильный для того, что вы хотите» (например, указывает на правильный тип). И это НЕКОТОРНО не скажет вам, указывает ли указатель на «устаревшие данные» (то есть, когда указатель WAS действителен, но теперь он используется для чего-то другого).

К сожалению, с 2 32 или 2 64 [фактически 2 48 ] возможно действительными адресами памяти в современной системе, почти невозможно знать, какие адреса действительны, а какие нет. Даже внутри операционной системы, как показывает ОС, если она может записать в память, которую вы попросили написать, это «попытаться написать ее, посмотреть, что произойдет». Для ОС это работает отлично, потому что это может быть осторожным, «это может пойти не так, и если это произойдет, я продолжу там в коде восстановления ошибок». ОС должна справиться с этим, потому что она должна принять, а) что программисты совершают ошибки, и б) что некоторые люди на самом деле пишу вредоносный код для TRY, чтобы разорвать ОС.

Способ для приложения «удостовериться, что указатели действительны» - это то, что программист пишет код, который ОСТОРОЖНО, о том, что он хранит в указателях, как он освобождает эти указатели и использует только указатели, в которых хранятся действительные значения. Вы не должны заканчивать «необходимость проверки правильности указателя» - тогда вы «делаете это неправильно».

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

Конечно, в C ++ существуют интеллектуальные указатели, векторы и различные другие инструменты, которые означают много времени, когда вам даже не нужно беспокоиться о указателях. Но понимание того, как использовать указатели и как работают указатели, по-прежнему хорошо.     

ответ дан Mats Petersson 20.06.2013 в 01:06
источник
3

Если указатель установлен в nullptr , это означает, что ему не был дан объект, на который он указывает, и вместо этого ему присваивается значение по умолчанию. Возможно, что указателю можно присвоить not nullptr и , но не назначить действительный объект, но в этом случае было бы невозможно определить что. Например:

С nullptr :

int *ptr = nullptr;

// check if pointer is unassigned to an object
if (ptr == nullptr) ptr = new int{0};

Без nullptr :

int *ptr;

// using ptr while uninitialized is Undefined Behavior!
if (ptr != &some_object)
    
ответ дан 0x499602D2 20.06.2013 в 00:47
источник