Forum Webscript.Ru

Программирование => Perl => Тема начата: novice2 от 18 Ноября 2004, 12:15:41

Название: pack() в unix
Отправлено: novice2 от 18 Ноября 2004, 12:15:41
Добрый  день.
Столкнулся с тем, что по разному работает pack(). Сокращенный пример:

#!/usr/bin/perl -w
use strict;
my $v = pack(\'Z*\',\'\');
print \'length=\'.length($v).\' data=\'.hexdump($v);

sub hexdump {
    my $data = shift;
    my $res = \'\';
    for(my $i=$[; $i      $res .= sprintf(\'%02x \',ord(substr($data,$i,1)));
    }
    return $res;
}

под windows active perl 5.6.1 выдает
length=1 data=00

под perl 5.005_03 solaris  выдает
length=0 data=

а модуль страдает стандартный, не мой, его исправлять не хотелось бы...
есть идеи?
Название: pack() в unix
Отправлено: NeoNox от 18 Ноября 2004, 13:43:40
Цитировать
novice2:
есть идеи?

есть. выводи отладочную информацию в hexdump
Название: pack() в unix
Отправлено: novice2 от 18 Ноября 2004, 14:02:10
NeoNox
извини - не понял.
я написал программу. отладил на виндоус - работает. перенес на солярис - не работает. выяснилось, что данные формируются неверно - неправильно работает функция pack(\'Z*\', $str) если $str содержит пустую строчку.pack(\'Z*\'...) должна выдать null-terminated строку (завершенную символом с кодом 0). И когда строка пустая, то должен получиться один байт - 0. Для проверки этого факта и приведен тестовый пример.
Название: pack() в unix
Отправлено: NeoNox от 18 Ноября 2004, 14:12:06
Цитировать
novice2:
извини - не понял.

поясню кодом:
sub hexdump {
my $data = shift;
my $res;
for(my $i=$[; $iprint $i.length($data)."\\n";
$res .= sprintf(\'%02x \',ord(substr($data,$i,1)));
print "$res\\n";
}
return $res;
}
Что в результате?
Название: pack() в unix
Отправлено: novice2 от 18 Ноября 2004, 15:25:51
появилась возможность проверить на солярисе версию 5.8.5.
оказалось, дело в версии перла. в 5.0 pack() неверно работает для пустой строки. но там, где эта прога будет работать, перл обновить непросто :(

NeoNox
сама hexdump неоднократно проверена.
в таком варианте:
 
#!/usr/bin/perl -w
use strict;
my $v = pack(\'Z*\',\'\');
print \'length=\'.length($v).\' data=\'.hexdump($v);

sub hexdump {
  my $data = shift;
  my $res;
  for(my $i=$[; $i    print \'i=\'.$i.\' length=\'.length($data)."\\n";
    $res .= sprintf(\'%02x \',ord(substr($data,$i,1)));
    print "res=$res\\n";
  }
  return $res;
}

новый перл выдает:
i=0 length=1
res=00
length=1 data=00

а старый:
Use of uninitialized value at t3.pl line 4.
length=0 data=
Название: pack() в unix
Отправлено: NeoNox от 18 Ноября 2004, 17:36:58
novice2 ну новая версия делает для тебя поблажку.
Вот скажи мне, зачем ты в pack передаешь пустое значение?
Название: pack() в unix
Отправлено: novice2 от 18 Ноября 2004, 18:01:50
NeoNox
ИМХО это не поблажка, а корректнная работа. модификатор Z велит создать строку, завершенную 0. Я передаю пустую строку (ну это я ДОЛЖЕН сделать, там опциональные параметры). И пустая строка должна преобразоваться в 0 символов + байт 0 - итого 1 байт. Новый перл так и работает. Строка, завершенная 0 никогда не может быть короче 1 байта, теоретически. Это стандартный модуль Net::SMPP. И из-за этого бага неверно формируются пакеты протокола :(