В языке C ++ (согласно C ++ 03) в самой попытке использовать значение недопустимого указателя вызывает неопределенное поведение. Нет необходимости разыгрывать его для UB. Достаточно просто прочитать значение указателя. Концепция «недопустимое значение», вызывающая UB, когда вы просто пытаетесь прочитать это значение, фактически распространяется почти на все скалярные типы, а не только на указатели.
После delete
указатель обычно недействителен в этом конкретном смысл, т. е. чтение указателя, который якобы указывает на то, что только что было «удалено», приводит к неопределенному поведению.
int *p = new int();
delete p;
int *p1 = p; // <- undefined behavior
Вызов функции-члена с помощью недопустимого указателя - это только конкретный случай выше. Указатель используется как аргумент для неявного параметра this
. Передача указателя является аргументом без ссылки - это акт его чтения, поэтому поведение в вашем примере не определено.
Итак, ваш вопрос действительно сводится к тому, почему чтение недопустимых значений указателя вызывает неопределенное поведение ,
Ну, может быть много причин для конкретной платформы. Например, на некоторых платформах акт чтения указателя может привести к тому, что значение указателя будет загружено в определенный выделенный адресный регистр. Если указатель недействителен, оборудование / ОС может немедленно обнаружить его и вызвать ошибку программы. Фактически, так работает наша популярная платформа x86 в отношении сегментных регистров. Единственная причина, по которой мы ничего не слышим, это то, что популярные ОС придерживаются модели с плоской памятью, которая просто не активно использует регистры сегментов.
C ++ 11 фактически утверждает, что dereferencing недопустимые значения указателя вызывает поведение undefined , в то время как все другие недопустимые значения указателя вызывают поведение, определенное реализацией . Он также отмечает, что поведение, определяемое реализацией в случае «копирования недопустимого указателя», может привести к «системному сбою во время выполнения». Таким образом, на самом деле можно было бы тщательно маневрировать через лабиринт спецификации C ++ 11 и успешно прийти к выводу, что вызов не виртуального метода с помощью недопустимого указателя должен привести к реализации поведение, упомянутое выше. В любом случае всегда будет существовать «системная ошибка выполнения».
Это должно получить Вас достаточно близкий:
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
ForceDataValidation();
}
private static void ForceDataValidation()
{
TextBox textBox = Keyboard.FocusedElement as TextBox;
if (textBox != null)
{
BindingExpression be = textBox.GetBindingExpression(TextBox.TextProperty);
if (be != null && !textBox.IsReadOnly && textBox.IsEnabled)
{
be.UpdateSource();
}
}
}
Самый легкий путь состоит в том, чтобы установить фокус где-нибудь. Можно сразу задержать фокус, но установка фокуса где угодно инициирует LostFocus-событие на любом типе управления и заставит его обновить свой материал:
IInputElement x = System.Windows.Input.Keyboard.FocusedElement;
DummyField.Focus();
x.Focus();
Иначе должен был бы получить сфокусированный элемент, получить обязательный элемент от сфокусированного элемента и инициировать обновление вручную. Пример для TextBox и ComboBox (необходимо было бы добавить любое управление, вводит Вас, должен поддерживать):
TextBox t = Keyboard.FocusedElement as TextBox;
if ((t != null) && (t.GetBindingExpression(TextBox.TextProperty) != null))
t.GetBindingExpression(TextBox.TextProperty).UpdateSource();
ComboBox c = Keyboard.FocusedElement as ComboBox;
if ((c != null) && (c.GetBindingExpression(ComboBox.TextProperty) != null))
c.GetBindingExpression(ComboBox.TextProperty).UpdateSource();
Также посмотрите на предложения в этот сообщение