Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
 |  |  |
Да. 16.08.01 16:57 Число просмотров: 896
Автор: XR <eXtremal Research> Статус: The Elderman Отредактировано 16.08.01 17:04 Количество правок: 2
|
> > 1) Написать класс массива с контролем индексов и > throw() > > при выходе за границу > > 2) Если это Win32 то использовать вместо catch() > except() > > > > BTW: код приводимый сообщением выше можно заставить > ловить > > исключения > > если приладить ЗА границей массива защищенную от > доступа > > страницу > > это уже вариация на тему 1+2 > > не знаю как на других платформах, но x86 + Win эта вещь не > будет вызывать никаких исключений - ни C++ ни SEH. потому > как массивы размещаются на стеке, а стек достаточно велик > чтобы не вызывать нарушения доступа к памяти (если конечно > гигабайты на него не класть).
Xmm ... под *NIX это делается очень легко ...
/*грубо слепленый код*/
template <class T, int a>
class Safe
{
public:
T A[a];
char prot_page[4096];
Safe() {mprotect(prot_page,4096,PROT_NONE);}
~Safe() {mprotect(prot_page,4096,PROT_READ|PROT_WRITE);}
}
....
Safe<char,10> x;// аналог x[10];
x.A[0]='a'; // все OK
x.A[10]='b'; // ловим SIGSEGV
Разве в Win32 нет аналога mprotect ? (лень лезть в мануал :))
> > данный код вызывает разрушение данных хранящихся на стеке и > как следствие адрес возврата из процедуры. блок catch уже > закрылся а уж потом происходит ret по кривому адресу вот > тут то и возникает исключение которое и ловит ось.
Это будет криво работать если за a[10] будут еще какие либо данные
они просто будут побиты до кучи ... а SEH может и не сработать ...
|
|
<programming>
|
[C++] Обработка исключений 16.08.01 14:52
Автор: myrmidon Статус: Незарегистрированный пользователь
|
Можно ли как нить ловить ошибки типа выход за пределы массива?
Пробывал так :
try
{
char mass[10];
strcpy(mass, "hvjkhjkdshfjkhfjkshfjkhjhfjkhfjkhfjhfjhfjkhfjhfjkdhfjkshfjkshfkjhfkjhfkjfh");
}
catch(...)
{
// обработка исключения
}
но что то нифига! вылезает мессага "Программа выполнела недопустимую операцию и будет закрыта"!
|
 |
[C++] Обработка исключений 17.08.01 18:17
Автор: m_fox Статус: Незарегистрированный пользователь
|
В VC есть способ:
__try
{
}__except(1)
{
}
такой код перехватывает действительно все исключения, но есть ограничения на использование такой конструкции.
Подробнее читай MSDN.
> Можно ли как нить ловить ошибки типа выход за пределы > массива? > Пробывал так : > try > { > char mass[10]; > strcpy(mass, > "hvjkhjkdshfjkhfjkshfjkhjhfjkhfjkhfjhfjhfjkhfjhfjkdhfjkshfj > kshfkjhfkjhfkjfh"); > } > catch(...) > { > // обработка исключения > } > > но что то нифига! вылезает мессага "Программа выполнела > недопустимую операцию и будет закрыта"!
|
 |
Да. 16.08.01 15:01
Автор: XR <eXtremal Research> Статус: The Elderman
|
1) Написать класс массива с контролем индексов и throw() при выходе за границу
2) Если это Win32 то использовать вместо catch() except()
BTW: код приводимый сообщением выше можно заставить ловить исключения
если приладить ЗА границей массива защищенную от доступа страницу
это уже вариация на тему 1+2
|
 |  |
Да. 16.08.01 16:43
Автор: cb <cb> Статус: Member
|
> 1) Написать класс массива с контролем индексов и throw() > при выходе за границу > 2) Если это Win32 то использовать вместо catch() except() > > BTW: код приводимый сообщением выше можно заставить ловить > исключения > если приладить ЗА границей массива защищенную от доступа > страницу > это уже вариация на тему 1+2
не знаю как на других платформах, но x86 + Win эта вещь не будет вызывать никаких исключений - ни C++ ни SEH. потому как массивы размещаются на стеке, а стек достаточно велик чтобы не вызывать нарушения доступа к памяти (если конечно гигабайты на него не класть).
данный код вызывает разрушение данных хранящихся на стеке и как следствие адрес возврата из процедуры. блок catch уже закрылся а уж потом происходит ret по кривому адресу вот тут то и возникает исключение которое и ловит ось.
|
 |  |  |
Да. 16.08.01 16:57
Автор: XR <eXtremal Research> Статус: The Elderman Отредактировано 16.08.01 17:04 Количество правок: 2
|
> > 1) Написать класс массива с контролем индексов и > throw() > > при выходе за границу > > 2) Если это Win32 то использовать вместо catch() > except() > > > > BTW: код приводимый сообщением выше можно заставить > ловить > > исключения > > если приладить ЗА границей массива защищенную от > доступа > > страницу > > это уже вариация на тему 1+2 > > не знаю как на других платформах, но x86 + Win эта вещь не > будет вызывать никаких исключений - ни C++ ни SEH. потому > как массивы размещаются на стеке, а стек достаточно велик > чтобы не вызывать нарушения доступа к памяти (если конечно > гигабайты на него не класть).
Xmm ... под *NIX это делается очень легко ...
/*грубо слепленый код*/
template <class T, int a>
class Safe
{
public:
T A[a];
char prot_page[4096];
Safe() {mprotect(prot_page,4096,PROT_NONE);}
~Safe() {mprotect(prot_page,4096,PROT_READ|PROT_WRITE);}
}
....
Safe<char,10> x;// аналог x[10];
x.A[0]='a'; // все OK
x.A[10]='b'; // ловим SIGSEGV
Разве в Win32 нет аналога mprotect ? (лень лезть в мануал :))
> > данный код вызывает разрушение данных хранящихся на стеке и > как следствие адрес возврата из процедуры. блок catch уже > закрылся а уж потом происходит ret по кривому адресу вот > тут то и возникает исключение которое и ловит ось.
Это будет криво работать если за a[10] будут еще какие либо данные
они просто будут побиты до кучи ... а SEH может и не сработать ...
|
 |  |  |  |
Работающий код оказался куда более сложным но он работает :) 16.08.01 17:30
Автор: XR <eXtremal Research> Статус: The Elderman Отредактировано 16.08.01 17:32 Количество правок: 1
|
Ради прикола привожу subj :)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// Use libExcept (SEH style signal wrapper)
#include "except.hpp"
#ifndef PAGESIZE
#define PAGESIZE 4096
#endif
template <class T, int a>
class Safe
{
void* p;
public:
T* A;
char* prot_page;
Safe()
{
p = malloc(sizeof(T)*a+2*PAGESIZE-1);
prot_page = (char *)(((int) p + a*sizeof(T) + PAGESIZE-1) & ~(PAGESIZE-1));
A = (T*)((int)prot_page-a*sizeof(T));
mprotect(prot_page,PAGESIZE,PROT_NONE);
}
~Safe()
{
mprotect(prot_page,PAGESIZE,PROT_READ | PROT_WRITE);
free(p);
}
};
int main( int argc, char *argv[])
{
int i;
Safe<char,10> X;
__ExceptLib.SetSystemException(SIGSEGV, AT_HANDLED);
__try {
for(i=0;i<20;i++)
{
X.A[i]=(char)('A'+i);
printf("X[%d]=%c\n",i,X.A[i]);
}
}__except(SysException e){
printf("Bad index %d\n",i);
}__end_except;
return 0;
} ---
Фокус заключается в том что данные приходится выравнивать на конец страницы
|
 |  |  |  |
Да. 16.08.01 17:29
Автор: cb <cb> Статус: Member
|
> /*грубо слепленый код*/ > template <class T, int a> > class Safe > { > public: > T A[a]; > char prot_page[4096]; > Safe() {mprotect(prot_page,4096,PROT_NONE);} > ~Safe() {mprotect(prot_page,4096,PROT_READ|PROT_WRITE);} > } > > .... > > Safe<char,10> x;// аналог x[10]; > x.A[0]='a'; // все OK > x.A[10]='b'; // ловим SIGSEGV > > Разве в Win32 нет аналога mprotect ? (лень лезть в мануал > :))
есть, VirtualProtect(Ex), только guard page должна находится на выровненной на PAGE_SIZE границе, т.е. если у тебя размер рабочего массива меньше PAGE_SIZE, то образуется дельта свободного места между ним и guard page.
> Это будет криво работать если за a[10] будут еще какие либо > данные > они просто будут побиты до кучи ... а SEH может и не > сработать ...
угу.
|
 |  |  |  |  |
Да. 16.08.01 17:36
Автор: XR <eXtremal Research> Статус: The Elderman
|
> есть, VirtualProtect(Ex), только guard page должна > находится на выровненной на PAGE_SIZE границе, т.е. если у > тебя размер рабочего массива меньше PAGE_SIZE, то > образуется дельта свободного места между ним и guard page.
См. пример листинга с выравниванием данных на
КОНЕЦ страницы ... :)))
Лозунг дня: Даешь процы с аппаратной страницей в двойное слово :))))
|
 |  |  |  |  |  |
[C++] а по проще можно какнить сделать???? 16.08.01 18:00
Автор: myrmidon Статус: Незарегистрированный пользователь
|
|
|
 |  |  |  |  |  |  |
[C++] Угу ... не писать кривой код типа того что ты привел :) Ну или юзать генераторы кода, основанные на формальных спецификациях. Но это на 3 порядка заковыристей приведенного мной кода :) 16.08.01 20:18
Автор: XR <eXtremal Research> Статус: The Elderman
|
|
|
 |  |  |  |  |  |  |  |
[C++] Угу ... не писать кривой код типа того что ты привел :) Ну или юзать генераторы кода, основанные на формальных спецификациях. Но это на 3 порядка заковыристей приведенного мной кода :) 17.08.01 01:34
Автор: myrmidon Статус: Незарегистрированный пользователь
|
|
ндааа, тада проще самому контролировать все значения и проверять все размеры, мляяя
|
 |  |  |  |  |  |  |  |  |
[C++] По-моему "1)" намного проще, хоть и тормозливее 17.08.01 07:43
Автор: Бяша <Biasha> Статус: Member Отредактировано 17.08.01 07:47 Количество правок: 1
|
>>>>>>>>1) Написать класс массива с контролем индексов и throw() при выходе за границу
К тому же цитата в тему:
"...что нет проверки выхода за границы вектора и т.д. Ответ на подобные
возражения таков: "Вы можете запрограммировать это сами." Давайте посмотрим,
действительно ли оправдан такой ответ. Другими словами, проверим средства
абстракции языка C++, попытавшись реализовать эти возможности для векторных
типов, которые мы создадим сами, и посмотрим, какие с этим связаны трудности,
каких это требует затрат, и насколько получившиеся векторные типы удобны в
обращении.
class vector {
int* v;
int sz;
public:
vector(int); // конструктор
~vector(); // деструктор
int size() { return sz; }
void set_size(int);
int& operator[](int);
int& elem(int i) { return v[i]; }
};
Функция size возвращает число элементов вектора, таким образом индексы должны
лежать в диапазоне 0 ... size()-1. Функция set_size сделана для изменения
этого размера, elem обеспечивает доступ к элементам без проверки индекса,
а operator[] дает доступ с проверкой границ.
Идея состоит в том, чтобы класс сам был структурой фиксированного размера,
управляющей доступом к фактической памяти вектора, которая выделяется
конструктором вектора с помощью распределителя свободной памяти new:
vector::vector(int s)
{
if (s<=0) error("плохой размер вектора");
sz = s;
v = new int[s];
}
Теперь вы можете описывать вектора типа vector почти столь же элегантно, как
и вектора, встроенные в сам язык:
vector v1(100);
vector v2(nelem*2-4);
Операцию доступа можно определить как
int& vector::operator[](int i)
{
if(i<0|sz<=i) error("индекс выходит за границы");
return v[i];
}
"Введение в язык С++" Бьярн Страустрап, 1995 г.
---
Это конечно не быстрая аппаратная проверка, зато работать будет везде, и не сложно для понимания.
Если цель в контроле, а не в оптимальности - то это тебе подойдёт. Иначе пиши без ошибок или жди исполнения лозунга дня :)
|
 |  |  |  |  |  |  |  |  |  |
[C++] а по-моему, намного проще использовать STL и нефиг велосипед изобретать; пишешь vector a[100] и все 17.08.01 11:35
Автор: Qrot Статус: Незарегистрированный пользователь
|
|
|
 |  |  |  |  |  |  |  |  |  |  |
[C++] токо от тупого memcpy(a,b,c) не спасает ни разу :)) (см. первоначальный код) 17.08.01 11:57
Автор: XR <eXtremal Research> Статус: The Elderman
|
|
|
 |  |  |  |  |  |  |  |  |  |  |  |
[C++] не спасает, но memcpy вроде как и не очень нужен теперь :) - см. vector::insert 17.08.01 12:55
Автор: Qrot Статус: Незарегистрированный пользователь
|
первоначальная проблема вполне ясна, только это ИМХО не есть хорошо - испльзовать конструкции C++ в C-подобном коде.
посему и предлагается STL - оно кстати и полезно для изучения. у нас в конторе например на кандидатов на работу свотрят косо если чел
говорит что плюсы "знает в совершенстве" а об STL ни малейшего понятия
|
 |  |  |  |  |  |  |  |  |  |  |  |  |
[C++] не спасает, но memcpy вроде как и не очень нужен теперь :) - см. vector::insert 17.08.01 13:42
Автор: XR <eXtremal Research> Статус: The Elderman
|
> первоначальная проблема вполне ясна, только это ИМХО не > есть хорошо - испльзовать конструкции C++ в C-подобном > коде.
Это не есть плохо если это к месту ... просто нужно чувствовать
оба стиля - в этом кстати и заключается сила (и успех) C++
как ГИБРИДНОГО языка ....
> посему и предлагается STL - оно кстати и полезно для > изучения. у нас в конторе например на кандидатов на работу > свотрят косо если чел > говорит что плюсы "знает в совершенстве" а об STL ни > малейшего понятия
Ну это ваши проблемы :)))
Мне например STL не нравится категорически хотя вроде бы уже является стандартом плюсов
Я использую свои поделки - правда они появились еще до STL
и сразу были заточены на:
- тотальную синхронизацию в многопоточном окружении (в STL на эту тему 2,5 класса)
- максимальную производительность со статической структурой данных (максимально быстрый доступ к данным
при относительно неоптимальной стратегии изменения структуры данных )
- применение различных алтернативных схем аллокации (например аллокация через mmap :))
вообще ++ позволяют смотреть гораздо шире чем это позволяет сделать STL
да и применять "корпоративные стандарты" в голом R&D где результат строго говоря точно не определен
я бы не стал...
Да и порой бывает прикольно слышать крики в общем то неплохих программеров "подсевших" на STL
и налетевших на невозможность сделать ту или иную фичу в его рамках STL
|
 |  |  |  |  |  |  |  |  |  |  |  |  |  |
[C++] не спасает, но memcpy вроде как и не очень нужен теперь :) - см. vector::insert 17.08.01 14:36
Автор: Qrot Статус: Незарегистрированный пользователь
|
> Мне например STL не нравится категорически хотя вроде бы > уже является стандартом плюсов мне тоже многое что в нем не нравится и много в нем не хватает...
как и в стандартной C-шной либе, в общем-то - где там синхронизация между потоками или работа с сокетами? :)
а не помешало бы
но в этом примере STL (или любая нормальная плюсовая либо) все же к месту - согласен? :))
|
|
|