Нужная информация там бесспорно есть, но парсить этот файл на каждый раз, как нужно узнать права доступа к памяти - это слишком медленно. Есть другие варианты?
Вот для установки прав доступа есть mprotect(), а на получение прав доступа я системного вызова не нашел.
Этот код будет в библиотеке. Если ставить обработчик, нужно потом его восстанавливать - а это влечет за собой применение мер для нормальной работы в многопоточном окружении. Не хотелось бы такое городить.
А в винапи такая функция была, но после win9x отпилили, ибо мудачество. Там, кстати(в оффтопе), такое через SEH рекомендуют проверять, по крайней мере я такую реализацию видел.
> все равно засада в многопоточных ситуациях, спасибо. Придется городить свой обработчик сигнала.
Вообще говоря, даже с обработчиком засада - между проверкой памяти и ее использованием проходит некоторое время, и за него зашита може измениться. Классическая гонка.
>В идеале, мне нужна такая функция:
>
>bool is_pointer_readable(void *p);
void* не может быть разыменован.
Можно попробовать что-нибудь вроде (каждый раз открывать файл, выделять память и проч., естественно, не обязательно):
int is_read_ptr(void *ptr, int size)
{
int fd, rc;
char *buf = (char *)malloc(size);
fd = open("/proc/self/mem", O_RDONLY);
rc = pread(fd, buf, size, (unsigned long)ptr);
close(fd);
free(buf);
return rc == size;
}
> Вообще говоря, даже с обработчиком засада - между проверкой памяти и ее использованием проходит некоторое время, и за него зашита може измениться. Классическая гонка.
Я это и имею ввиду - ставить обработчик и пытаться использовать память. При неудаче будет сигнал, при удаче - дело уже сделано.
Самый переносимый метод -- попросить ядро почитать из этой памяти. Открываешь /dev/null, вызываешь системный вызов write() в него, указав в качестве адреса буфера интересующий адрес, в качестве длины -- интересующую длину. Если этого участка памяти нет в твоём адресном пространстве, системный вызов вернёт ошибку. Не скажу какую, read(2) нет под рукой. Точно также можно проверять "писабельность", открывая /dev/zero и вызывая read() из него в интересующий участок памяти. Работать будет на любом UNIX-е.