September 2nd, 2014

Violet smoker

Рыжеголовая рыба-бабочка

И ещё одна рыбка, встретившаяся мне только в открытом море - на сей раз из бабочек (внимание, по клику - везде большие фото /с автоматической тоновой коррекцией корелом/!):



Плавают они обычно па́рами, но в кадр попадали либо вот так:



Либо слегка и́здали - как вот здесь, с полосатыми родственницами, лимонными рыбами-ласточками и самцом ржавого попугая:



Collapse )
Violet smoker

Прибрежный городок в районе Коста-дель-Маресме

Пролетев над горами, самолёт выскочил к побережью - вот так оно выглядит с высоты птичьего полёта (внимание, по клику - большое фото):

IMG_0921.JPG

Я бы предположил, что на снимке - Матаро: это раза в два дальше от Барселоны, чем я жил. Но уверенности нет...
Violet smoker

А вот кто ещё помнит седьмой Delphi?

Коллегу попросили слегка поколупаться в старом проекте:



Приходит ко мне - грит, я в шоке: убил полдня - задница! Ничего не понимаю! Не работает! Давай вместе посмотрим!

Итак, имеется DLL-ка, в ней две функции:

Load1: function (aS: pChar): boolean; stdcall = nil;
Load2: function (aS: pChar; var codeErr: LongInt): boolean; stdcall = nil;


Инициализация:

@Load1 := GetProcAddress (hLib, 'Load1');
@Load2 := GetProcAddress (hLib, 'Load2');


Вызов Load1:

procedure PerformLoad (TaskObject: TTaskObject);
var
ErrorCode: integer;
s: string;
begin
s := TaskObject.RequestText;
if Load1 (@s[1]) then // вызов старой функции библиотеки
ErrorCode := 0
else
ErrorCode := 1;
TaskObject.ErrorCode := ErrorCode;
end;


Вызов снаружи:

// Инициализация объекта LocalTaskObject
...
PerformLoad (LocalTaskObject);
if (LocalTaskObject.ErrorCode = 0) then
...


Всё работало. Но. Надо ему было заменить Load1 на Load2:

procedure PerformLoad (TaskObject: TTaskObject);
var
ErrorCode: Integer;
s: string;
begin
s := TaskObject.RequestText;
Load2 (@s[1], ErrorCode); // вызов новой функции библиотеки
TaskObject.ErrorCode := ErrorCode;
end; //Вот здесь ещё всё хорошо - объект TaskObject в отладчике "живой"


И внезапно:

// Инициализация объекта LocalTaskObject
...
PerformLoad (LocalTaskObject); // передаём "живой" объект
if (LocalTaskObject.ErrorCode = 0) then // и внезапно вот здесь LocalTaskObject становится nil
...


Увидев подобное, я несколько прифигел. В чём разница? Что может освобождать или затирать объект? Ладно, говорю, давай попробуем тупой костыль:

function PerformLoad (TaskObject: TTaskObject): TTaskObject;
var
ErrorCode: integer;
s: string;
begin
s := TaskObject.RequestText;
Load2 (@s[1], ErrorCode); // вызов новой функции библиотеки
TaskObject.ErrorCode := ErrorCode;
result := TaskObject;
end;
// Вызов
// Инициализация объекта LocalTaskObject
...
LocalTaskObject := PerformLoad (LocalTaskObject); // передаём "живой" объект
if (LocalTaskObject.ErrorCode = 0) then // и внезапно всё опять заработало
...


Но как?