ysth đã yêu cầu tôi về IRC để nhận xét về câu hỏi của bạn. Tôi đã thực hiện toàn bộ đống công cụ "tháo" perl được biên dịch và nội dung (chỉ cần xem trang CPAN của mình [http://search.cpan.org/~jjore]).
Perl biên dịch nguồn của bạn thành một cây có kích thướccấu trúc mà thỉnh thoảng có C con trỏ tới SV*
là giá trị perl. Hiện tại, phân đoạn cốt lõi của bạn đã bị xóa một trong số các mã OP*
và SV*
được lưu trữ.
Thế giới tốt nhất có thể là có mô-đun perl như B::Deparse thực hiện công việc thông tin cho bạn. Nó hoạt động bằng cách sử dụng giao diện ánh sáng cho bộ nhớ perl trong các lớp B::OP
và B::SV
(được ghi trong B, perlguts và perlhack).Điều này là không thực tế đối với bạn bởi vì một đối tượng B::*
là chỉ là một con trỏ vào bộ nhớ với các trình truy cập để giải mã cấu trúc cho việc sử dụng của chúng tôi. Xem xét:
require Data::Dumper;
require Scalar::Util;
require B;
my $value = 'this is a string';
my $sv = B::svref_2object(\ $value);
my $address = Scalar::Util::refaddr(\ $value);
local $Data::Dumper::Sortkeys = 1;
local $Data::Dumper::Purity = 1;
print Data::Dumper::Dumper(
{
address => $address,
value => \ $value,
sv => $sv,
sv_attr => {
CUR => $sv->CUR,
LEN => $sv->LEN,
PV => $sv->PV,
PVBM => $sv->PVBM,
PVX => $sv->PVX,
as_string => $sv->as_string,
FLAGS => $sv->FLAGS,
MAGICAL => $sv->MAGICAL,
POK => $sv->POK,
REFCNT => $sv->REFCNT,
ROK => $sv->ROK,
SvTYPE => $sv->SvTYPE,
object_2svref => $sv->object_2svref,
},
}
);
mà khi chạy cho thấy rằng đối tượng B::PV
(nó là ISA B::SV
) là thật sự chỉ đơn thuần là một giao diện để các đại diện bộ nhớ của chuỗi biên soạn this is a string
.
$VAR1 = {
'address' => 438506984,
'sv' => bless(do{\(my $o = 438506984)}, 'B::PV'),
'sv_attr' => {
'CUR' => 16,
'FLAGS' => 279557,
'LEN' => 24,
'MAGICAL' => 0,
'POK' => 1024,
'PV' => 'this is a string',
'PVBM' => 'this is a string',
'PVX' => 'this is a string',
'REFCNT' => 2,
'ROK' => 0,
'SvTYPE' => 5,
'as_string' => 'this is a string',
'object_2svref' => \'this is a string'
},
'value' => do{my $o}
};
$VAR1->{'value'} = $VAR1->{'sv_attr'}{'object_2svref'};
Tuy nhiên điều này có nghĩa là bất kỳ B::*
sử dụng mã thực sự phải hoạt động vào bộ nhớ trực tiếp. Tye McQueen nghĩ rằng ông nhớ một trình gỡ lỗi C mà hoàn toàn có thể làm sống lại một quá trình làm việc được đưa ra một bãi chứa lõi. My gdb
không thể. gdb
có thể cho phép bạn đổ nội dung của các cấu trúc OP*
và SV*
của bạn. Bạn rất có thể sẽ chỉ đọc các cấu trúc đã bị bán phá giá để diễn giải cấu trúc chương trình của bạn. Nếu bạn muốn, hãy sử dụng gdb
để đổ các cấu trúc, sau đó tổng hợp các đối tượng B::*
đối tượng hoạt động trong giao diện giống như chúng bình thường và sử dụng B::Deparse
trên đó. Tại gốc, deparser của chúng tôi và gỡ lỗi khác bán phá giá công cụ chủ yếu là đối tượng theo định hướng để bạn chỉ có thể "đánh lừa" chúng bằng cách tạo ra một đống giả B::*
lớp học và các đối tượng.
Bạn có thể đọc phương thức coderef2text
của B :: Deparse lớp hướng dẫn. Nó chấp nhận một tham chiếu chức năng, phôi nó vào một đối tượng B::CV
, và sử dụng nó để đầu vào cho các phương pháp deparse_sub
:
require B;
require B::Deparse;
sub your_function { ... }
my $cv = B::svref_2object(\ &your_function);
my $deparser = B::Deparse->new;
print $deparser->deparse_sub($cv);
Đối với lời giới thiệu nhẹ nhàng để OP*
và ý tưởng liên quan, vui lòng xem cập nhật PerlGuts Illustrated và Optree guts.
Josh, cảm ơn câu trả lời chi tiết. Điều này khá nhiều người vợ với những gì tôi mong đợi. Trông giống như một dự án cho những đêm mùa đông dài. – otmar