Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2011.08.28;
Скачать: [xml.tar.bz2];

Вниз

Как влияет 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.004 c
15-1304220544
PiterPen
2011-05-01 07:29
2011.08.28
Delphi x64


15-1304454597
Юрий
2011-05-04 00:29
2011.08.28
С днем рождения ! 4 мая 2011 среда


1-1264484580
HF-Trade
2010-01-26 08:43
2011.08.28
Артефакты при двойной буферизации


15-1305059392
Юрий
2011-05-11 00:29
2011.08.28
С днем рождения ! 11 мая 2011 среда


15-1305056428
И. Павел
2011-05-10 23:40
2011.08.28
Как получить список запущенных приложений из сервиса





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский