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

Вниз

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

 
_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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.57 MB
Время: 0.055 c
1-1184325115
atruhin
2007-07-13 15:11
2007.09.23
Не работает Anchors с MDIChild формой


15-1187779706
Piter
2007-08-22 14:48
2007.09.23
А чем автомат лучше пробок?


15-1187811709
Vlad Oshin
2007-08-22 23:41
2007.09.23
Великое Северное море.


15-1188204481
zdm77
2007-08-27 12:48
2007.09.23
Локальные админы


15-1187797221
Неудачник
2007-08-22 19:40
2007.09.23
Программисты – это армия физиков-неудачников





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