Нашел ошибку, что дальше?

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Нашел ошибку, что дальше?

Сообщение mike » 13.11.2009 06:18:57

В библиотеке unix/ipc.pp (строка 422) неправильно описана функция:
Код: Выделить всё
Function semctl(semid:cint; semnum:cint; cmd:cint; var arg: tsemnum); cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'semctl'; {$endif}

Должно быть:
Код: Выделить всё
Function semctl(semid:cint; semnum:cint; cmd:cint; arg: tsemnum); cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'semctl'; {$endif}

Что с этим делать?
mike
новенький
 
Сообщения: 40
Зарегистрирован: 23.02.2007 17:25:00

Re: Нашел ошибку, что дальше?

Сообщение Mr.Smart » 13.11.2009 12:10:59

Если вы эту функцию используете самостоятельно то переопределите её в своём коде!
Код: Выделить всё
...
implementation
...
function semctl(semid:cint; semnum:cint; cmd:cint; arg: tsemnum); cint; cdecl; external name 'semctl';
...
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Нашел ошибку, что дальше?

Сообщение Sergei I. Gorelkin » 13.11.2009 12:24:23

Есть пример или тест, подтверждающий, что оно именно так должно быть?
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1407
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Нашел ошибку, что дальше?

Сообщение mike » 13.11.2009 15:54:36

Переопределить то я могу, но хотелось бы избавить общественность от ошибки :) А я ее и без переопределения могу использовать, вот установка нуля:
Код: Выделить всё
semctl(SemHandle, 0, SEM_SETVAL, PSemun(0)^);


Самым лучшим доказательством будет пример использования этой функции прямо в других C-программах:
Код: Выделить всё
void init_semaphore( int sid, int semnum, int initval)
{
        union semun semopts;   

        semopts.val = initval;
        semctl( sid, semnum, SETVAL, semopts);
}

Как видите, четвертым параметром передается сам semopts, а не ссылка на него. А если использовать декларацию из unix/ipc.pp, например для установки значения, то либо вызов возвращает ошибку ERANGE, либо устанавливает совсем левое, весьма высокое значение семафора.

Да и если посмотреть на описание SEmun, то непонятно зачем передавать его как var-параметр, ведь те поля, которые данная функция может записывать, уже являются указателями, адрес самого semun ей совершенно для этого не нужен.
mike
новенький
 
Сообщения: 40
Зарегистрирован: 23.02.2007 17:25:00

Re: Нашел ошибку, что дальше?

Сообщение Sergei I. Gorelkin » 13.11.2009 17:40:15

В сишном объявлении semctl() используется "..." (переменное число параметров), а такие параметры в Си неявно передаются по ссылке, поэтому наличие var в объявлении FPC формально правильно.
Кроме того, в FPC в случае параметра типа запись (а тип semun - это вариантная запись) вызывающая сторона по-любому передает указатель, а разница между передачей по ссылке и по значению состоит только в копировании параметра на вызываемой стороне.
Поэтому у меня складывается впечатление, что, если оно не работает, то ошибка таки где-то в другом месте.

Наконец, если браться это исправлять, то нужно патчить не только unix/ipc.pp, но и остальные объявления - для freebsd, solaris и т.п.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1407
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Нашел ошибку, что дальше?

Сообщение mike » 14.11.2009 02:31:18

Если запись вне зависимости от размера передается по ссылке, то значит четвертый параметр должен или иметь тип platform integer. Факт остается фактом, код такого вида работает неправильно или вообще не работает:
Код: Выделить всё
var
  Val: TSemun;
begin
  ...
  Val.val:= 0;
  if semctl(semid, 0, SEM_SETVAL, Val) = 0 then
  ...

А приведенный выше кастинг PSemun(value)^ -- работает. Более того, в юните libc эта функция имеет третий параметр типа integer и работает нормально (у меня эта проблема вылезла именно после перехода с libc на ipc).

Добавлено спустя 47 минут 58 секунд:
Небольшая поправка, не работает это под x86_64, под i386 все действительно нормально. Вот тестовый код:
Код: Выделить всё
uses
  BaseUnix, IPC;
var
  Val: TSemun;
  sem: cint;
begin
  Val.val:= 123;
  sem:= semget(111, 1, IPC_CREAT);
  if semctl(sem, 0, SEM_SETVAL, Val) = 0 then
    WriteLn('Semval: ', semctl(sem, 0, SEM_GETVAL, Val))
  else
    WriteLn('Error: ', errno);
  semctl(sem, 0, IPC_RMID, Val);
end.

Под x64 выдает "Error: 34", а если в первом semctl вписать PSemun(123)^, то начинает работать правильно. Файл ipc.pp один и тот же. Нужно думать что с этим делать.
mike
новенький
 
Сообщения: 40
Зарегистрирован: 23.02.2007 17:25:00

Re: Нашел ошибку, что дальше?

Сообщение Sergei I. Gorelkin » 14.11.2009 10:55:27

Ага, так уже становится понятнее, куда копать. Раскопки показывают наличие каких-то мрачных заморочек, по этой теме висят два незакрытых бага, http://bugs.freepascal.org/view.php?id=13363 и http://bugs.freepascal.org/view.php?id=14075. По второй ссылке есть патч.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1407
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Нашел ошибку, что дальше?

Сообщение mike » 14.11.2009 18:08:41

Да, спасибо. Похоже этот Pablo Alfaro все сделал правильно. Неясно только почему один и тот же системный вызов под разными платформами по-разному использовать нужно.
mike
новенький
 
Сообщения: 40
Зарегистрирован: 23.02.2007 17:25:00


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

Рейтинг@Mail.ru