2011-01-06 3 views
1

Есть функция, аналогичная IsBadReadPtr в Unix? По крайней мере, некоторые функции IsBadReadPtr? Я хочу написать процедуру, которая будет реагировать, если что-то происходит с процессом (например, SIGSEGV) и восстановить некоторую информацию. Но я хочу проверить указатели, чтобы убедиться, что данные не повреждены и посмотреть, можно ли их безопасно получить. В противном случае сама процедура обработки сбоев рухнет, что станет бесполезным.IsBadReadPtr analogue on Unix

Любые предложения?

+1

[Не использовать IsBad * Ptr.] (Http://blogs.msdn.com/b/oldnewthing/archive/2006/09/27/773741.aspx) – ephemient

ответ

7

Обычный способ сделать это в системах POSIX - использовать системный вызов write(). Он вернется EFAULT в errno вместо того, чтобы поднимать сигнал, если память не может быть прочитана:

int nullfd = open("/dev/random", O_WRONLY); 

if (write(nullfd, pointer, size) < 0) 
{ 
    /* Not OK */ 
} 
close(nullfd); 

(/dev/random хорошее устройство использовать для этого на Linux, так как он может быть записан любым пользователем и будет на самом деле попробовать для чтения данной памяти. В ОС без /dev/random или там, где она не может быть записана, попробуйте /dev/null). Другой альтернативой будет анонимный канал, но если вы хотите протестировать большую область, вам нужно будет регулярно очищать считывающий конец трубы.

+0

Это решение не работает в Linux 3.8.7 ... write() ALWAYS возвращает успех, если 'fd' равно/dev/null, даже если «указатель» равен NULL. – etherice

+0

В Linux вы можете использовать '/ dev/random' - я обновил ответ. – caf

+0

Это вещь POSIX или просто вещь для Linux для/dev/random write() для изменения пула энтропии? Если по какой-либо причине или на какой-то платформе это не имеет никакого эффекта, ядро ​​может решить пропустить операцию записи и вернуть успех сразу, как это делает с/dev/null в качестве оптимизации. Без таких гарантий я все равно был бы взволнован по поводу этого решения. – etherice

1

Вы никогда не можете сказать «безопасно ли доступ к указателю», в Windows или Unix. Но для некоторой подобной информации о некоторых платформах unix, проверьте cat /proc/self/maps.

+1

Если я запускаю под gdb, я могу отображать место памяти и gdb либо отображали бы что-то, либо говорили бы мне: «Невозможно получить доступ к памяти по адресу blah-blah». Поэтому он знает, могу ли я или не могу получить доступ к адресу blah-blah - интересно, как я мог бы сделать то же самое из своей программы. – StasM

+0

@StasM: gdb делает хорошие догадки. Также он обращается к памяти в * другом * процессе через ptrace pokes, так что это нормально, если он сработает. – ephemient

0

Как вы можете это сделать?

Вы пытаетесь это сделать, а затем обрабатываете ошибку.

Для этого сначала вы установите sigsetjmp и обработчик сигнала SIGSEGV. Затем попытайтесь использовать указатель. Если это был плохой указатель, вызывается обработчик SIGSEGV, и вы можете перейти к безопасности и сообщить об ошибке пользователю.

+0

Если я попытаюсь сделать это внутри обработчика SIGSEGV, он станет довольно сложным ... Также может быть SIGBUS. – StasM

+0

Используйте signalfd(). С ним проще работать и поточно-безопасно. – asdf