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

Вниз

Про компилятор   Найти похожие ветки 

 
_Mike_   (2007-08-10 17:31) [0]

Доброго времени суток!

Тут где-то тема была про Delphi компилятор. Ну вот вам пример.

const
 DEVICE_ADDRESS_LENGTH  = 6;
 DEVICE_CLASS_LENGTH    = 3;
 MAX_DEVICE_NAME_LENGTH = 64;

 BTSTATUS_FAIL                 = $00000000;

type
 PBLUETOOTH_DEVICE_INFO_EX = ^BLUETOOTH_DEVICE_INFO_EX;
 BLUETOOTH_DEVICE_INFO_EX = record
   dwSize:          DWORD;
   address:         array [0..DEVICE_ADDRESS_LENGTH - 1] of Byte;
   classOfDevice:   array [0..DEVICE_CLASS_LENGTH - 1] of Byte;
   szName:          array [0..MAX_DEVICE_NAME_LENGTH - 1] of Char;
   bPaired:         BOOL;
   ucLmpVersion:    UCHAR;
   wManuName:       Word;
   wLmpSubversion:  Word;
   reserved:        array [0..15] of Byte;
   wClockOffset:    Word;
   bConnected:      BOOL;
   dwDataRecvBytes: DWORD;
   dwDataSentBytes: DWORD;
   cSignalStrength: Char;
 end;

 PBT_GetLocalDeviceInfo     = function (dwMask: DWORD; var pDevInfo: BLUETOOTH_DEVICE_INFO_EX): DWORD; cdecl;

var
 _BT_GetLocalDeviceInfo:     PBT_GetLocalDeviceInfo     = nil;

function BT_GetLocalDeviceInfo(dwMask: DWORD; var pDevInfo: BLUETOOTH_DEVICE_INFO_EX): DWORD;
begin
 if Assigned(_BT_GetLocalDeviceInfo) then
   Result := _BT_GetLocalDeviceInfo(dwMask, pDevInfo)

 else
   Result := BTSTATUS_FAIL;
end;

function TBFBluetoothRadio.GetName: string;
var
 hRadio: THandle;
 BSInfo: BLUETOOTH_DEVICE_INFO_EX;
 MSInfo: BLUETOOTH_RADIO_INFO;
begin
 { TODO : Get Name }
 case FAPI of
   baBlueSoleil: begin
                   FillChar(BSInfo, SizeOf(BSInfo), 0);
                   BSInfo.dwSize := SizeOf(BSInfo);

                   if BT_GetLocalDeviceInfo(MASK_DEVICE_NAME, BSInfo) = BTSTATUS_SUCCESS then Result := string(BSInfo.szName);
                 end;

   baMicrosoft: begin
                     end;
                end;
 end;
end;


Внимание вопрос!

При выходе из функции AV.

Все параметры 100% верные.


 
oldman ©   (2007-08-10 17:42) [1]

А можно тоже самое, но нормально?
Я такого кривого кода давно не видел!!!


 
boa_kaa ©   (2007-08-10 17:47) [2]

Два вопроса:
1) в какой функции?
2) F7 & F8 сломаны?


 
MBo ©   (2007-08-10 17:52) [3]

>BLUETOOTH_DEVICE_INFO_EX = record
не packed record?

PBT_GetLocalDeviceInfo   - cdecl - это точно?

ошибка не с работой со строками связана?


 
tesseract ©   (2007-08-10 17:54) [4]


> Я такого кривого кода давно не видел!!!


ага, там явно PackedRecord. а BOOL там случайно не интом быть дожен ?


 
_Mike_   (2007-08-10 17:55) [5]


> MBo ©   (10.08.07 17:52) [3]


не packed, 100% cdecl, е со строками. Вот это работает:

procedure TBFBluetoothDiscovery.EnumRadiosBlueSoleil(Radios: TBFBluetoothRadios);
var
 Info: BLUETOOTH_DEVICE_INFO_EX;
 Radio: TBFBluetoothRadio;
 Addr: BLUETOOTH_ADDRESS;
begin
 FillChar(Info, SizeOf(Info), 0);
 Info.dwSize := SizeOf(Info);

 if BT_GetLocalDeviceInfo(MASK_DEVICE_ADDRESS, Info) = BTSTATUS_SUCCESS then begin
   Radio := TBFBluetoothRadio.Create;

   CopyMemory(@Addr.rgBytes[0], @Info.address[0], 6);

   with Radio do begin
     FAddress := BluetoothAddressToString(Addr.ullLong);
     FAPI := baBlueSoleil;
   end;

   Radios.FList.Add(Radio);
 end;
end;


В том же модуле. (MASK_DEVICE_NAME и MASK_DEVICE_ADDRESS на падение после GetName не влияют)

Подсказка - херится стек в _BT_GetLocalDeviceInfo (при вызове из GetName)


 
_Mike_   (2007-08-10 17:56) [6]


> ага, там явно PackedRecord. а BOOL там случайно не интом
> быть дожен ?

Не пакед. BOOL = DWORD = LongInt = Cardinal


 
_Mike_   (2007-08-10 17:59) [7]


> А можно тоже самое, но нормально?


Привидите пример кода, соответствующего Вашим высоким стандартам - я переформатирую.


> Я такого кривого кода давно не видел!!!

Я не просил комментировать оформление кусков кода вырезанные из разных модулей. Однако их более чем достаточно для того, чтобы вышеуказанное скомпилять.


> boa_kaa ©   (10.08.07 17:47) [2]
> Два вопроса:
> 1) в какой функции?
> 2) F7 & F8 сломаны?


Два ответа:
1) GetName.
2) Для Вас - да.


 
Rouse_ ©   (2007-08-10 18:02) [8]


> не packed, 100% cdecl,

А откедаль ты данную функцию берешь? irprops.cpl не экспортирует такого чуда, а то, что экспортирует - все сплош STDCALL


 
_Mike_   (2007-08-10 18:07) [9]


> Rouse_ ©   (10.08.07 18:02) [8]

BlueSoleil SDK


 
_Mike_   (2007-08-10 18:11) [10]

#ifdef __cplusplus
extern "C" {
#endif

#define BTEXPORT

#define DEVICE_ADDRESS_LENGTH   6
#define DEVICE_CLASS_LENGTH   3
#define MAX_DEVICE_NAME_LENGTH   64

#define BTSTATUS_SUCCESS   0x00000001

typedef struct _BLUETOOTH_DEVICE_INFO_EX {
DWORD dwSize;
BYTE address[DEVICE_ADDRESS_LENGTH];
BYTE classOfDevice[DEVICE_CLASS_LENGTH];
CHAR szName[MAX_DEVICE_NAME_LENGTH];
BOOL bPaired;
UCHAR ucLmpVersion;
WORD wManuName;
WORD wLmpSubversion;
BYTE reserved[16];
WORD wClockOffset;
BOOL bConnected;
DWORD dwDataRecvBytes;
DWORD dwDataSentBytes;
CHAR cSignalStrength;
} BLUETOOTH_DEVICE_INFO_EX, *PBLUETOOTH_DEVICE_INFO_EX;

BTEXPORT DWORD BT_GetLocalDeviceInfo (
       /* [in] */ DWORD dwMask,
       /* [out] */ PBLUETOOTH_DEVICE_INFO_EX pDevInfo
       );


 
tesseract ©   (2007-08-10 18:31) [11]


> Не пакед. BOOL = DWORD = LongInt = Cardinal


как не packed  у тебя там WORD!!!!! в с++ все записи упакованы по умолчанию. да и явно там STDCALL, в С++ он по умолчанию такой __cdecl не вижу я в функции.


 
Rouse_ ©   (2007-08-10 18:47) [12]

Хм... в сях выравнивание по умолчанию включено... а стек плывет бо CDECL дергает add.


 
_Mike_   (2007-08-10 18:51) [13]


> в с++ все записи


> #ifdef __cplusplus
> extern "C" {
> #endif



> Rouse_ ©   (10.08.07 18:47) [12]

Лучше поверьте - что там cdecl и нет выравнивания - это установлено 100%


 
_Mike_   (2007-08-10 18:54) [14]

Код из [5] работает. Грабля именно в GetName.
Да и в другом коде все также и работает.


 
_Mike_   (2007-08-10 18:59) [15]

По спец заказам - дабы убедить вас и убедиться еще раз самому - написал packed + stdcall - результат - вываливается раньше (в EnumRadios) так как соответствнно и параметры и вызов не верен.


 
Rouse_ ©   (2007-08-10 22:06) [16]


> Лучше поверьте - что там cdecl и нет выравнивания - это
> установлено 100%

Есть возможность выложить проект в том варианте, где четко детектируется ошибка? Я не могу выступать в роли отладчика, читая код с экрана :)
Если есть возможность - то оригинальные VC++ исходники демки приветствуются...


 
_Mike_   (2007-08-10 22:17) [17]


> Есть возможность выложить проект в том варианте, где четко
> детектируется ошибка?

Ошибка четко детектируется в функции GetName. Проект можете взять на сайте, а по поводу cdecl и packed/не packed - тут есть у человека сырцы - может подтвердить что оно cdecl и ну packed. И даже работает.

К сожалению - проект я выложить не могу по той причине, что проект коммерческий.

Код выше полность компилируемый (за исключением лишнего end в case который я не удалил (не заметил)). Достаточно его поместить в любой юнит и вызвать GetName.

максимум, что могу добавить:

hLib := LoadLibrary("btfunc.dll");

_BT_GetLocalDeviceInfo     := GetProcAddress(hLib, "BT_GetLocalDeviceInfo");


P.S. Тема была создана в основном в ответ на тему про компилятор, которая здесь проскакивала, а где мне популярно объяснили что я ламер... Ну вот вам задачка из тойже серии. Когда дельфевый компилятор падает на ровном месте и создает огромное количество гемороя для разработчика.


 
tesseract ©   (2007-08-10 22:38) [18]


>  Когда дельфевый компилятор падает на ровном месте и создает
> огромное количество гемороя для разработчика.


Ессно Delphi всегда имел проблемы с "отражением" памяти на структуры, а драйверы часто так пишуться.

> Хм... в сях выравнивание по умолчанию включено... а стек
> плывет бо CDECL дергает add.


Возможно, я в сях не очень, в EVC там выравнивание я не заметил - добивалось вручную Reserved, возможно проблема API от производителя данного девайса.  


>     if BT_GetLocalDeviceInfo(MASK_DEVICE_NAME, BSInfo) =
> BTSTATUS_SUCCESS then Result := string(BSInfo.szName);


гм, что то подсказывает, что  возможны проблемы как раз с прямым  приведением к string, у тебя szName запросто исчезнет при выходе из функции.

ЗЫ: Я уже пью пиво :-)


 
Servelat ©   (2007-08-10 23:01) [19]

> Когда дельфевый компилятор падает на ровном месте и создает
> огромное количество гемороя для разработчика.


Стало интересно. Не поленился запустить делфи.


> Код выше полность компилируемый


Не знаю как у Вас, а у меня делфи не знает ни что такое BLUETOOTH_RADIO_INFO ни что за FAPI который Вы case (ни даже что за класс TBFBluetoothRadio). Конструктивный разговор возможен когда вы выложите конкретный _компилирующийся_ пример, а иначе все всегда можно списать на ошибку в 17 строке.

Когда я был молод и юн, и только поступил в университет, а с делфи был знаком понаслышке, в одном проекте ловил AV при вызове виртуальной функции своего класса. Полчаса отлаживал (и материл компилятор, разработчиков и Гейтса), пока не обнаружил, что в одном месте попутал индексы и вышел за границу массива, чем испортил указатель на экземпляр объекта. Это к слову, как ошибка в одном месте может вызывать падение программы совсем в другом.

У меня нет сомнений в том, что делфевый компилятор неидеален. Однако "падает на ровном месте" это явно не про него. За все время пока я с ним работаю, у меня небыло к нему нареканий. Был разок обнаружен "небезопасный код" в VCL, много раз были ошибки из-за собственных кривых рук, но компилятор всегда был на высоте. Хотя не так давно была ветка про передачу динамического массива пустому конструктору, ну что ж, и на Солнце бывают пятна ;)

PS

> Проект можете взять на сайте,

Настолько же информативно как "рыбу обычно можно поймать в воде" или "вода, как правило, кипит при 100? С при нормальном атмосферном давлении".

PPS
 Заменив все неизвестные константы нулями либо единицами, и изменив функцию до следующего вида:

function BT_GetLocalDeviceInfo(dwMask: DWORD; var pDevInfo: BLUETOOTH_DEVICE_INFO_EX): DWORD;
begin
 Result := 1;
 pDevInfo.szName := "test";
end;


вызов GetName ошибки не "детектирует".


 
tesseract ©   (2007-08-10 23:12) [20]


> Не знаю как у Вас, а у меня делфи не знает ни что такое
> BLUETOOTH_RADIO_INFO ни что за FAPI который Вы case (


Не паясничай, ясно, что переводить заголовки API  к одной из самых распространённых программ для соединия с BlueTooth никто не захочет.

Кстати интересен сам  факт объявления указателя на структуру и передачи его в функцию по ссылке - что несколько разные вещи, может надо как раз указатель в функцию передавать? с выделенной под него памятью.

> var  _BT_GetLocalDeviceInfo:     PBT_GetLocalDeviceInfo
>     = nil;

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

и тут не засёк выделения:

>  _BT_GetLocalDeviceInfo(dwMask, pDevInfo)


 
oxffff ©   (2007-08-10 23:35) [21]

Вот пример. cdecl нормально работает.

  PBT_GetLocalDeviceInfo= function (dwMask: DWORD; var pDevInfo: BLUETOOTH_DEVICE_INFO_EX): DWORD; cdecl;

var
 Form1: TForm1;

implementation

{$R *.dfm}
function Myfunc(dwMask: DWORD; var pDevInfo: BLUETOOTH_DEVICE_INFO_EX): DWORD; cdecl;
begin
//Do someThing
pDevInfo.szName:="All works properly";
result:=0;
end;

var FuncUnknown:PBT_GetLocalDeviceInfo=Myfunc;

function callFunc(dwMask: DWORD; var pDevInfo: BLUETOOTH_DEVICE_INFO_EX ):DWORD;
begin
result:=FuncUnknown(dwmask,pDevInfo);
end;

function abc:string;
var BSInfo:BLUETOOTH_DEVICE_INFO_EX;
begin
FillChar(BSInfo, SizeOf(BSInfo), 0);
BSInfo.dwSize := SizeOf(BSInfo);
callFunc(10,BSInfo);
result:=string(BSInfo.szName);
result:=BSInfo.szName;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage(abc);
end;


 
Rouse_ ©   (2007-08-10 23:39) [22]


> Проект можете взять на сайте, а по поводу cdecl и packed/не
> packed - тут есть у человека сырцы - может подтвердить что
> оно cdecl и ну packed.

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


 
_Mike_   (2007-08-10 23:42) [23]


> tesseract ©   (10.08.07 23:12) [20]

Отправил мылом полный проект. Падает в AV при GetName (запускаем демку - видим результат).

Тоже самое работает в EnumRadios.

Для запуска и отлова глюка - BlueSoleil1,6 или 2.3 (скачать можно здесь: http://www.btframework.com/support.htm)

P.S. Сюда просьба не постить то что отправил - того что я запостил здесь - более чем достаточно.


 
_Mike_   (2007-08-10 23:43) [24]


> Rouse_ ©   (10.08.07 23:39) [22]

Я где-то просил решить проблему????? Перечитайте внимательно всю ветку.


 
_Mike_   (2007-08-10 23:44) [25]


> tesseract ©   (10.08.07 23:12) [20]

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


 
_Mike_   (2007-08-10 23:49) [26]


> Кстати интересен сам  факт объявления указателя на структуру
> и передачи его в функцию по ссылке - что несколько разные
> вещи, может надо как раз указатель в функцию передавать?
>  с выделенной под него памятью.

var параметрв и передача указателя - синонимы. Т.е. при var передается фактически указатель.

Если оттрасирровать стек то все вроде бы ничего, пока не входим в _BT_GetLocalInfo. И вот тут начинаются чудеса.
Хз что дельфя там генерит на стеке, но функция затирает адрес возврата и херит часть полей структуры. Однако! Имя она вс=таки заполняет. Однакоже ни один регистр или что-то еще не страают в итоге. У меня такое ощущение что проблема с тем по границе какого адреса Delphi размещает параметры в стеке. (ща попробую AllocateMemory заюзать для структуры).

С другой стороны не понятно почему тот же вызов работает в EnumRadios.....


 
oxffff ©   (2007-08-10 23:55) [27]


> Подсказка - херится стек в _BT_GetLocalDeviceInfo (при вызове
> из GetName)


А что под отладчиком нельзя посмотреть?.

Вот вызов вашей функции

1:
push @pDevInfo
push dwMask
call [_BT_GetLocalDeviceInfo]
add esp,8; //это точно cdecl вызов
2:

Где валится?  Как конкретно стек затирается?


 
oxffff ©   (2007-08-11 00:00) [28]


> Хз что дельфя там генерит на стеке, но функция затирает
> адрес возврата и херит часть полей структуры


Ай да чудеса.
А слабо посмотреть размер структуры в С++ и сравнить ее с BSInfo.dwSize?


 
_Mike_   (2007-08-11 00:09) [29]


> А слабо посмотреть размер структуры в С++ и сравнить ее
> с BSInfo.dwSize

Конечно. Я же дебил, до такого догадаться не мог без Вашего совета.


 
oxffff ©   (2007-08-11 00:11) [30]


> Конечно. Я же дебил, до такого догадаться не мог без Вашего
> совета.


Да вы зря обижаетесь.
Если вы говорите, про перетирание адреса возврата, то явно что-то не в порядке.
Вы лучше скажите какой адрес перетирается

Адрес возврата в BT_GetLocalDeviceInfo?


 
_Mike_   (2007-08-11 00:13) [31]


> oxffff ©   (11.08.07 00:11) [30]

Если размер структуры не валидны - функция вернет INVALID_ARGUMENT.

Сейчас попробую отловить место где киляется адрес возврата (я уже 3 день воюю с этой херней)


 
oxffff ©   (2007-08-11 00:13) [32]

Или Адрес возврата в GetName?


 
oxffff ©   (2007-08-11 00:19) [33]

А попробуйте сделать так.

function TBFBluetoothRadio.GetName: string;
var
hRadio: THandle;
PBSInfo: PBLUETOOTH_DEVICE_INFO_EX;
begin
{ TODO : Get Name }
case FAPI of
  baBlueSoleil: begin
                   new(PBSInfo);
                    zeromemory(PBSInfo,sizeof(BLUETOOTH_DEVICE_INFO_EX));
                     PBSInfo^.dwSize := SizeOf(BLUETOOTH_DEVICE_INFO_EX);
                    if BT_GetLocalDeviceInfo(MASK_DEVICE_NAME, PBSInfo^) = BTSTATUS_SUCCESS then Result := PBSInfo^.szName;
                   dispose(PBSInfo);
                  end;

end;
end;

Перетирание должно убраться.
А если нет, то тем еще хуже.


 
_Mike_   (2007-08-11 00:19) [34]

Итак:

0012F300 - 0047c425 - адрес возврата из _BT_GetLocalInfo (из DLL)
0012F304 - 00000001 - MASK_NAME
0012F308 - 0012F534 - адрес структуры (в стеке естественно)

0012F534 - начало структуры
0012F5AC - последний DWORD структуры
0012F5В0 - 0012F5E4 - указатель стека на что-то (сохранен при вызове GetName)
0012F5B4 - 00481533 - адрес возврата из GetName

после вызова _BT_GetLocalInfo перед возвратом из GetName (когда уже эпилог прошел перед ret)
0012F5В0 - 00000000 - указатель стека на что-то (сохранен при вызове GetName)
0012F5B4 - 00000000 - адрес возврата из GetName


 
_Mike_   (2007-08-11 00:20) [35]


> oxffff ©   (11.08.07 00:19) [33]

Делал - один хер. Только в другом адресе AV вылетает (так AV 0/0, а если выделять память - то с другими циферками :)


 
oxffff ©   (2007-08-11 00:22) [36]

Если перетирание адреса возврата не уберется, то значит проблема в логике
external процедуры. А если да , значит проблема скорее всего как в несоответствии структур и так в возможно логике.
Идею вы надеюсь поняли. Пусть уж лучше кучу перетирает.


 
_Mike_   (2007-08-11 00:23) [37]

Посмотрел EnumRadios - такого поведения не наблюдается - т.е. дело не в _BF_GetLocalInfo (хотя я уже хер знает что и думать).


 
_Mike_   (2007-08-11 00:25) [38]


> oxffff ©   (11.08.07 00:22) [36]

Я уверен что не в функции. Потому как этот код работает в предыдущей версии. Он там точно такой же (за исключением того, что GetName вынесена отдельной процедурой)
Но! Даже если я добавляю в GetName флаги, которые используются в пердыдущей версии (т.е. копирую код полностью) - ничего не меняется - все также сыпется.


 
oxffff ©   (2007-08-11 00:27) [39]


> _Mike_   (11.08.07 00:19) [34]


См. [27]

Ты лучше скажи значение esp до вызова call [_BT_GetLocalDeviceInfo] и до ret из процедуры. Надеюсь там не ret 8.


 
_Mike_   (2007-08-11 00:30) [40]


> oxffff ©   (11.08.07 00:27) [39]

Я это [27] третьи сутки наблюдаю...

Как положено - 0012F304

нет. там не ret 8



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

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

Наверх




Память: 0.59 MB
Время: 0.026 c
15-1187876173
iXT
2007-08-23 17:36
2007.09.23
Почему нельзя сменить ник(login) в анкете?


15-1188267803
ArtemESC
2007-08-28 06:23
2007.09.23
Ночью перечитал Евгения Онегина...


9-1143015328
Nic
2006-03-22 11:15
2007.09.23
Шейдеры: с чего начать?


11-1171784746
Ned
2007-02-18 10:45
2007.09.23
Закрытие программы :)


15-1187951223
palva
2007-08-24 14:27
2007.09.23
Индикатор настоящего программиста