Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.08.28;
Скачать: CL | DM;

Вниз

Как влияет Range check на работу результирующего кода?   Найти похожие ветки 

 
@!!ex ©   (2011-05-02 20:39) [0]

Ситуация:
Есть OGG плеер.
Если установлен Range check в настройках проекта - то все отлично работает.
Если снимаю Range check и пересобираю проект - вместо звука шум.

Естественно проблема где-то в моем коде, но я не могу понять где конкретно...
не плохо было бы понять, как влияет Range check на работу кода, чтобы понять где ошибка.


 
clickmaker ©   (2011-05-02 20:45) [1]

> как влияет Range check на работу кода

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


 
Дмитрий Тимохов   (2011-05-02 21:36) [2]

ну а может на ERangeError логика построена...


 
Германн ©   (2011-05-03 01:10) [3]


> Ситуация:
> Есть OGG плеер.
> Если установлен Range check в настройках проекта - то все
> отлично работает.
> Если снимаю Range check и пересобираю проект - вместо звука
> шум.
>

Не верю!


 
имя   (2011-05-03 12:40) [4]

Удалено модератором


 
@!!ex ©   (2011-05-03 14:08) [5]

> [1] clickmaker ©   (02.05.11 20:45)
> > как влияет Range check на работу кода
>
> контролирует выход за границы массива. Ошибки это может
> и не вызвать, но данные в стеке, например, могут быть испорчены

Я понимаю для чего сделан Range Check. Я не понимаю как он физически на код влияет.


> ну а может на ERangeError логика построена...

Там С++ либа. Я только методы из нее дергаю.
Соответственно Range Check как-то влияет на мой код, а на поведение либы влиять не может - либу то я не пересобираю.


> Не верю!

Последовательность действий:
ставлю Range check
пересобираю проект
все отлично работает
убираю Range check
пересобираю проект
вместо звука - шум
ставлю Range check
пересобираю проект
все отлично работает


 
clickmaker ©   (2011-05-03 14:19) [6]

> Я не понимаю как он физически на код влияет

посмотри в отладчике, в CPU window, один и тот же код с выключенным и включенным RC


 
clickmaker ©   (2011-05-03 14:29) [7]

если кратко, то в код вставляется сравнение текущего значения счетчика с размером массива (либо значения числа с мин/макс значениями), и при выходе за пределы вызывается BoundErr


 
QAZ   (2011-05-03 14:53) [8]

какая разница как он работает("обрезает" до границы) ? в любом случае ошибку надо править
проверяй все типы переменых которые передаеш функциям из либы


 
Sapersky   (2011-05-03 15:14) [9]

в код вставляется сравнение текущего значения счетчика с размером массива

Ещё Range Check проверяет выход переменных из диапазона (напр., Word - 0..65535).


 
RWolf ©   (2011-05-03 15:22) [10]


> Sapersky   (03.05.11 15:14) [9]

а не Overflow checking?


 
Sapersky   (2011-05-03 17:34) [11]

Range check проверяет при присвоении, например, такой код вылетает:

Var i : Integer;
   w : Word;

i := 65536; w := i;

хелп:
The $R directive enables or disables the generation of range-checking code. In the {$R+} state, all array and string-indexing expressions are verified as being within the defined bounds, and all assignments to scalar and subrange variables are checked to be within range. If a range check fails, an ERangeError exception is raised (or the program is terminated if exception handling is not enabled).

Неожиданно, да. Сам недавно включил RC в проекте и потом долго думал, отчего он начал вылетать на ровном месте через два часа работы (счётчик у таймера переполнялся).

Overflow проверяет ещё кое-что дополнительно:
w := 65536; Inc(w);
но если так:
w := 65536; w := w + 1;
то это считается случаем Range Check :)
В общем, разработчики явно рассчитывали на то, что включаться и выключаться будет всё вместе: "The $Q switch is usually used in conjunction with the $R switch".


 
@!!ex ©   (2011-05-03 17:46) [12]

> какая разница как он работает("обрезает" до границы) ? в
> любом случае ошибку надо править
> проверяй все типы переменых которые передаеш функциям из
> либы

ФИгово, когда не понимаешь что написано?
Я для этого и пытаюсь разобраться как работает range check - чтобы ошибку найти.
потому что я весь код прошерстил и не понимаю что в нем не так.


 
IPranker ©   (2011-05-03 18:14) [13]


> @!!ex ©   (03.05.11 17:46) [12]


Без кода не разобраться. :)


 
Sha ©   (2011-05-03 21:57) [14]

> @!!ex

Ты так и не сказал, предусмотрена ли у тебя обработка
соответствующей ошибки и не привел кода обработки.


 
KSergey ©   (2011-05-04 07:15) [15]

Исключения где-либо через try/except отлавливаются?


 
Думкин ©   (2011-05-04 07:15) [16]


> KSergey ©   (04.05.11 07:15) [15]

так в 17-й строке, вестимо.


 
Sha ©   (2011-05-04 08:21) [17]

Если код чужой, имеет смысл поискать что-нибудь похожее
на самопальный патчер кода в памяти или защиту от взлома.

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


 
@!!ex ©   (2011-05-04 08:33) [18]

Вот набросал код, который меняет свое поведение в зависимости от опции Range check

function  read_func (ptr:Pointer; size:integer; nmemb:integer; datasource:Pointer):integer; cdecl;
var
 F:Cardinal;
begin
 F:=Cardinal(datasource);
 Result:=FileRead(F,ptr^,size*nmemb);
end;
function  seek_func (datasource:pointer; offset:int64; whence:integer):integer; cdecl;
var
 F:Cardinal;
begin
 F:=Cardinal(datasource);
 FileSeek(F,offset,whence);
 Result:=0;
end;
function  close_func(datasource:pointer):integer; cdecl;
begin
 Result:=0;
end;
function  tell_func (datasource:pointer):integer; cdecl;
var
 F:Cardinal;
begin
 F:=Cardinal(datasource);
 Result:=FileSeek(F,0,1);
end;

const OGG_BUFFER_SIZE   = 1048576;
var
 buffer:array[0..OGG_BUFFER_SIZE-1] of char;

procedure alutLoadOGGFile(fname: string; var format: TALenum; var data: TALvoid; var size: TALsizei; var freq: TALsizei; var loop: TALint);
var
 F:Cardinal;
 cb:ov_callbacks;
 info:Pvorbis_info;
 oggFile:OggVorbis_File;

 bytes:integer;
 endian:integer;
 bitStream:integer;
begin
 endian:=0;
 F:=FileOpen(fname,fmOpenRead);
 cb.read_func:=read_func;
 cb.seek_func:=seek_func;
 cb.close_func:=close_func;
 cb.tell_func:=tell_func;

 ov_open_callbacks( Pointer(f), @oggFile, nil, -1, cb);

 Info := ov_info(@oggFile, -1);

 if (Info.channels = 1) then
   format := AL_FORMAT_MONO16
 else
   format := AL_FORMAT_STEREO16;
 // end if

 // The frequency of the sampling rate
 freq := Info.rate;

 size:=0;
 data:=nil;
 repeat

   bytes := ov_read(@oggFile, @Buffer[0], OGG_BUFFER_SIZE, endian, 2, 1, @bitStream);
   // Append to end of buffer

  size:=size+bytes;
  data:=ReallocMemory(Data,size);
  CopyMemory(Pointer(Integer(Data)+size-bytes),@Buffer[0],bytes);
 until bytes=0;

 ov_clear(@oggFile);
 FileClose(F);
end;


 
clickmaker ©   (2011-05-04 11:55) [19]

> меняет свое поведение в зависимости от опции Range check

меняет как?
ov_read вызывает read_func? все данные и правильно читаются этой функцией?

смущают вот такие тайпкасты Pointer(Integer(Data)+size-bytes)
по-хорошему, надо бы не Integer, а Cardinal, поскольку адрес - все-таки величина беззнаковая


 
QAZ   (2011-05-04 12:24) [20]


> ФИгово, когда не понимаешь что написано?
> Я для этого и пытаюсь разобраться как работает range check
> - чтобы ошибку найти.

читать умею и понимаю,только непонятно каким образом это поможет найти ошибку

> потому что я весь код прошерстил и не понимаю что в нем
> не так.

ну видимо вот это Pointer(Integer(Data)+size-bytes)
:)))


 
Игорь Шевченко ©   (2011-05-04 13:14) [21]


> поскольку адрес - все-таки величина беззнаковая


для Delphi ?


 
clickmaker ©   (2011-05-04 13:19) [22]

> для Delphi ?

то есть?


 
Anatoly Podgoretsky ©   (2011-05-04 13:23) [23]

> clickmaker  (04.05.2011 13:19:22)  [22]

Что есть.


 
Игорь Шевченко ©   (2011-05-04 13:49) [24]


> то есть?


ну у программ на delphi адресное пространство от 0 до почти $7FFFFFFF


 
DVM ©   (2011-05-04 17:57) [25]


> у у программ на delphi адресное пространство от 0 до почти
> $7FFFFFFF

Адресное пространство программ на делфи, как и любых 32 разрядных программ в Windows - 4 Гб. 32-х битный указатель может быть любым числом от 0 до 4"294"967"296 (от $00000000 до $FFFFFFFF).
А вот пользовательская часть простирается почти до $7FFFFFFF с дырками внутри возможно. Но пользовательскую часть можно и подвинуть попробовать до 3 гб.


 
Игорь Шевченко ©   (2011-05-04 20:34) [26]

DVM ©   (04.05.11 17:57) [25]


> 32-х битный указатель может быть любым числом от 0 до 4"294"967"296
> (от $00000000 до $FFFFFFFF).


если не секрет, откуда возьмется в программе на Delphi указатель больше $7FFFFFFF и куда он будет указывать ?


> Но пользовательскую часть можно и подвинуть попробовать
> до 3 гб.


На delphi ? Сильно сомневаюсь


 
Sha ©   (2011-05-04 21:08) [27]

Что знаковое, что беззнаковое - все равно команды сложения те же.

Судя по тому, что ТС тему исключений упорно замалчивает,
исключения у него не возникают.

Остается только спросить, как автор узнал, что приведенный код меняет свое поведение?
И почему сумев узнать, что дело в этих 40 строчках, он не узнал, в какой из них?


 
DVM ©   (2011-05-05 00:16) [28]


> Игорь Шевченко ©   (04.05.11 20:34) [26]


> На delphi ? Сильно сомневаюсь

Наверное ты читал это уже, но тут как раз о выделении памяти за пределами 2 гб:
http://www.gunsmoker.ru/2011/04/windows-spin-off.html


 
DVM ©   (2011-05-05 00:22) [29]


> http://www.gunsmoker.ru/2011/04/windows-spin-off.html

Я не проверял, но утверждается, что в 64 бит системах 32 бит программа и 4 гб выделить может.


 
Игорь Шевченко ©   (2011-05-05 00:34) [30]

DVM ©   (05.05.11 00:16) [28]


> Наверное ты читал это уже,


Читал.
Вот про трюк с $SetPEFlags я, честно говоря, напрочь забыл


 
han_malign   (2011-05-05 09:25) [31]


> по-хорошему, надо бы не Integer, а Cardinal

- на 32-битах(еще и без 3GB флага) по барабану(и $R+, по моему, в пролете), но лучше - PAnsiChar(Data)+size-bytes

на вскидку вижу:

> function  read_func (ptr:Pointer; size:integer; nmemb:integer;  datasource:Pointer):integer; cdecl;

size_t (*read_func)  (void *ptr, size_t size, size_t nmemb, void *datasource);

- size_t - обычно unsigned long,
но запрос больше 2Гб - как то маловероятен, и - вопрос, что библиотека с левым исключением делает...

Надо посмотреть что там в size и nmemb приходит...


 
DVM ©   (2011-05-05 13:40) [32]


> по-хорошему, надо бы не Integer, а Cardinal

По хорошему так:

NativeUInt(Data)+size-bytes


 
@!!ex ©   (2011-05-05 15:36) [33]

> Судя по тому, что ТС тему исключений упорно замалчивает,
>
> исключения у него не возникают.

Не понял, что я замалчиваю?
Исключения не возникает.


> Остается только спросить, как автор узнал, что приведенный
> код меняет свое поведение?
> И почему сумев узнать, что дело в этих 40 строчках, он не
> узнал, в какой из них?

Как я узнал - Сообщение номер 5.
Сократить до менее чем 40 строчек у меня пока не получилось.


 
@!!ex ©   (2011-05-05 15:37) [34]

> Надо посмотреть что там в size и nmemb приходит...

size=1
nmemb=65536


 
@!!ex ©   (2011-05-05 15:53) [35]

> Не понял, что я замалчиваю?

Я понял что я замалчивал. почему-то мозг постоянно игнорировал слово исключение.
Только на четвертное прочитание я все таки увидел слово "исключение".
Да, исключений нет никаких. Единственное проявление проблем - шум вместо звука.


 
clickmaker ©   (2011-05-05 15:59) [36]

сравни содержимое Data с RC и без. Хотя бы на предмет различий


 
@!!ex ©   (2011-05-05 16:01) [37]

там мегабайты данных...
Поверхностно проверял. те участки которые проверял - выглядат одинаково.
проверял выхлоп ov_read.
может Realloc гадость творит?
Сейчас попробую выделить метров 100 сразу и не делать Realloc


 
@!!ex ©   (2011-05-05 16:04) [38]

не в реаллоке дело.
сделал выделение одним блоком - ничего не поменялось.
однако!
сделал итератор, вместо вычисления указателя
 size:=0;
 data:=AllocMem(100000000);//  nil;
 it:=data;
 repeat

   bytes := ov_read(@oggFile, @Buffer[0], OGG_BUFFER_SIZE, endian, 2, 1, @bitStream);
   // Append to end of buffer

  size:=size+bytes;
//   data:=ReallocMemory(Data,size);
//   CopyMemory(Pointer(cardinal(Data)+size-bytes),@Buffer[0],bytes);
   CopyMemory(it,@Buffer[0],bytes);
   inc(it,bytes);
 until bytes=0;

и все заработало... Так отчего же старое не работало?


 
clickmaker ©   (2011-05-05 16:13) [39]

> Так отчего же старое не работало?

сравни сгенеренный asm-код закомментированного места с RC и без


 
@!!ex ©   (2011-05-05 16:22) [40]

Добавилось 4 строки:
0045985D 8B4DE8           mov ecx,[ebp-$18]
00459860 85C9             test ecx,ecx
00459862 7905             jns $00459869
00459864 E863A0FAFF       call @BoundErr

BoundErr не вызывается ни разу. То есть сам эксцепшн не возникает. Именно сопутствующий код как-то влияют.



Страницы: 1 2 вся ветка

Текущий архив: 2011.08.28;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.02 c
3-1262248374
12
2009-12-31 11:32
2011.08.28
можно как-то сделать быстрее?


15-1304595679
И. Павел
2011-05-05 15:41
2011.08.28
чтение системных журналов сообщений


2-1305295665
nicknolty
2011-05-13 18:07
2011.08.28
Непонятная кодировка


2-1305568293
volkafff
2011-05-16 21:51
2011.08.28
Классы


1-1265138738
Vincent
2010-02-02 22:25
2011.08.28
Как прочитать память у DLL (ReadProcessMemory):DllName.dll+offset