Главная страница
    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 не вызывается ни разу. То есть сам эксцепшн не возникает. Именно сопутствующий код как-то влияют.


 
@!!ex ©   (2011-05-05 16:23) [41]

Но он же не может никак влиять...
Сопутствующий код же не трогает сами данные...


 
@!!ex ©   (2011-05-05 18:32) [42]

Вынес вычисление указателя в отдельную строчку - все заработало как надо:
  It:=Pointer(cardinal(Data)+size-bytes);
  CopyMemory(It,@Buffer[0],bytes);


 
Sha ©   (2011-05-05 20:20) [43]

Ни разу не замечал, чтобы RangeCheck изменял
распределение регистров или переменных на стеке.
Но вдруг у тебя это не так.
Проверь свой исходный вариант на всякий случай.
Если окажется, что что-то меняется (стек или регистры),
то ov_read, возможно, это что-то портит.

И еще раз спрошу как ты узнал, что приведенный код
меняет свое поведение? А не ov_read?


 
Sha ©   (2011-05-05 20:47) [44]

> @!!ex
Если используешь Delphi 7, приведи здесь минимальный компилируемый без ошибок кусок кода.


 
Sha ©   (2011-05-05 20:58) [45]

> @!!ex
tell_func должна возвращать integer или int64?


 
@!!ex ©   (2011-05-05 21:47) [46]

> Если окажется, что что-то меняется (стек или регистры),
>
> то ov_read, возможно, это что-то портит.

Вроде бы не меняется.


> И еще раз спрошу как ты узнал, что приведенный код
> меняет свое поведение? А не ov_read?

Проверял Buffer который возвращает ov_read, вроде он одинаковый всегда.
Да и с чего бы ему менять свое поведение, он же в отдельной dll!


> [44] Sha ©   (05.05.11 20:47)
> Если используешь Delphi 7, приведи здесь минимальный компилируемый
> без ошибок кусок кода.

У меня Turbo Delphi 2006


> [45] Sha ©   (05.05.11 20:58)
> tell_func должна возвращать integer или int64?

long в C++ хедере. То есть дельфевый integer.

Вроде бы проблем аразрешилась вынесением расчета указателя в отдельную строку.
Видимо глюк компилятора? вероятно не имеет смысла дальше копать проблему. Просто время потратим.


 
Inovet ©   (2011-05-05 22:17) [47]

> [46] @!!ex ©   (05.05.11 21:47)
> Видимо глюк компилятора?

Ты же сказал, что ничего не менялось кроме

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

Глюка не видать.


 
Sha ©   (2011-05-05 22:23) [48]

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

Не разрешилась, а скорее всего упрятана еще глубже.

> Видимо глюк компилятора?

Видишь глюк в сгенерированном коде - покажи,
не видишь - не надо напраслины.
Какой может быть глюк, если распределение переменных
по регистрам и стеку то же самое?
Их порча в ov_read куда вероятнее.

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

Ну, тогда кидай батоны. А код все же приведи, будет время - гляну.


 
han_malign   (2011-05-06 10:10) [49]


> Вынес вычисление указателя в отдельную строчку - все заработало как надо:
>   It:=Pointer(cardinal(Data)+size-bytes);
>   CopyMemory(It,@Buffer[0],bytes);

- вот и проверь какой какой asm код генерируется в исходном и этом случае(*$R-*), раз место локализовано...

З.Ы. В отличие от D7, BDS уже не ругается на "signed/unsigned mismatch", а молча расширяет до int64(напоролся тут недавно...), возможно $R+/- меняет это поведение.
С короткой формой записи у D2k6(Express) проблемы(например Obj.MethodReturnedObj.Method - вываливается на этапе компиляции), так что это действительно может быть фичей глюкогенератора...


 
@!!ex ©   (2011-05-08 15:50) [50]

> А код все же приведи, будет время - гляну.

Я привел весь код загрузки OGG.
Выложить еще дополнительно всю инициализацию OpenAL, инициализацию Sound Buffer"a под полученные из OGG данные и создание Sound Source для воспризведения?


 
Мимо хотел пройти   (2011-05-08 18:42) [51]


> @!!ex ©   (08.05.11 15:50) [50]


Да, выложи пожалуйста.


 
Sha ©   (2011-05-09 02:47) [52]

> @!!ex ©   (08.05.11 15:50) [50]
> Я привел весь код загрузки OGG.

Ты пробовал компилировать, то что привел?

> Выложить еще дополнительно ... ?

Да мне пофиг.


 
@!!ex ©   (2011-05-09 09:42) [53]

> Ты пробовал компилировать, то что привел?

Конечно. А в чем проблема?


 
Sha ©   (2011-05-09 11:05) [54]

> А в чем проблема?

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

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


 
@!!ex ©   (2011-05-10 02:52) [55]

Этот код 1 в 1 повторяет код проекта на котором я проводил тесты, он тупо отткуда скопипастен.
Так что мне все еще не понятно в чем ваша проблема с компиляцией этого кода.


 
Sha ©   (2011-05-10 08:57) [56]

Наверно, в том, что я тоже ленив
и наперед знаю, что ни такой код


unit RangeCheckFormP;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs;

type
 TForm1 = class(TForm)
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

// тут твой код из [18]

end.


ни такой


program RangeCheckConsole;

{$APPTYPE CONSOLE}

uses
 SysUtils;

// тут твой код из [18]

begin
 { TODO -oUser -cConsole Main : Insert code here }
end.


даже не скомпилируется.



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

Форум: "Прочее";
Текущий архив: 2011.08.28;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.61 MB
Время: 0.004 c
2-1305549187
Соня
2011-05-16 16:33
2011.08.28
ADOConnection


15-1304972992
Юрий
2011-05-10 00:29
2011.08.28
С днем рождения ! 10 мая 2011 вторник


2-1305291291
AlekVolsk
2011-05-13 16:54
2011.08.28
Вынос модуля данных в DLL


15-1304540995
Юрий
2011-05-05 00:29
2011.08.28
С днем рождения ! 5 мая 2011 четверг


15-1304672702
OW
2011-05-06 13:05
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
Английский Французский Немецкий Итальянский Португальский Русский Испанский