Skip Menu |

This queue is for tickets about the Algorithm-SVM CPAN distribution.

Report information
The Basics
Id: 42500
Status: new
Priority: 0/
Queue: Algorithm-SVM

People
Owner: Nobody in particular
Requestors: fox [...] ucw.cz
Cc: perl [...] luther.ca
AdminCc:

Bug Information
Severity: Unimportant
Broken in: 0.13
Fixed in: (no value)



Subject: During Algorithm::SVM destruction "Use of uninitialized value in null operation" warning is shown.
Hi, I use Algorithm::SVM version 0.13, perl version 5.10.0 and Debian testing. During the destruction of Algorithm::SVM object, warning "Use of uninitialized value in null operation" is printed. This behaviour can be reproduced by adding "use warnings;" as the first line of test.pl in the source package and running "make test". The warning is printed just after the "Checking svm destructor" line. The problem is the following: during the construction of the object, an empty object is created and blessed 'Algorithm::SVM'. Then, a call is made into the .so file, where another object is created, blessed and finally stored in $self->{svm}. During the destruction, there are two objects to DESTROY -- the 'outer' object, which contains only ->{svm} field, and 'inner' object, which really needs to be destroyed. But both are blessed into 'Algorithm::SVM', so a DESTROY method in .so is called twice. For the outer object, it prints the mentioned warning. I attach a patch, which gets rid of the outer object. Only the inner object is preserved and acts as the outer object too. The "make test" works fine after applying this patch, and the warning is gone. Have a nice day, Milan Straka PS: Just FYI, the test.pl prints another warning, because of the line "ok($svm->getLabels(), (10, 0, -10));". The list (10,0,-10) acts as the second, third and fourth argument to the 'ok' function :)
The patch did not get attached, sorry :( Milan On Sun Jan 18 14:44:31 2009, straka.milan wrote: Show quoted text
> Hi, > > I use Algorithm::SVM version 0.13, perl version 5.10.0 and Debian testing. > > During the destruction of Algorithm::SVM object, warning "Use of > uninitialized value in null operation" is printed. This behaviour can be > reproduced by adding "use warnings;" as the first line of test.pl in the > source package and running "make test". The warning is printed just > after the "Checking svm destructor" line. > > The problem is the following: during the construction of the object, an > empty object is created and blessed 'Algorithm::SVM'. Then, a call is > made into the .so file, where another object is created, blessed and > finally stored in $self->{svm}. > > During the destruction, there are two objects to DESTROY -- the 'outer' > object, which contains only ->{svm} field, and 'inner' object, which > really needs to be destroyed. But both are blessed into > 'Algorithm::SVM', so a DESTROY method in .so is called twice. For the > outer object, it prints the mentioned warning. > > I attach a patch, which gets rid of the outer object. Only the inner > object is preserved and acts as the outer object too. The "make test" > works fine after applying this patch, and the warning is gone. > > Have a nice day, > Milan Straka > > PS: Just FYI, the test.pl prints another warning, because of the line > "ok($svm->getLabels(), (10, 0, -10));". The list (10,0,-10) acts as the > second, third and fourth argument to the 'ok' function :)
--- lib/Algorithm/SVM.pm.ori 2009-01-18 11:14:18.000000000 +0100 +++ lib/Algorithm/SVM.pm 2009-01-18 20:19:56.000000000 +0100 @@ -279,7 +279,6 @@ sub new { my ($class, %args) = @_; - my $self = bless({ }, $class); # Ensure we have a valid SVM type. $args{Type} = 'C-SVC' if(! exists($args{Type})); @@ -299,8 +298,8 @@ my $nu = exists($args{Nu}) ? $args{Nu} + 0 : 0.5; my $epsilon = exists($args{Epsilon}) ? $args{Epsilon} + 0 : 0.1; - $self->{svm} = _new_svm($svmtype, $kernel, $degree, $gamma, $coef0, - $c, $nu, $epsilon); + my $self = _new_svm($svmtype, $kernel, $degree, $gamma, $coef0, + $c, $nu, $epsilon); # Load the model if one was specified. if(my $model = $args{Model}) { @@ -311,7 +310,7 @@ $self->load($model); # Ensure that the model loaded correctly. - croak("Error loading model file: $model") if(! $self->{svm}); + croak("Error loading model file: $model") if(! $self); } return $self; @@ -323,7 +322,7 @@ # Check if we got a dataset object. croak("Not an Algorithm::DataSet") if(ref($x) ne "Algorithm::SVM::DataSet"); - return _predict($self->{svm}, $x); + return _predict($self, $x); } sub predict_value { @@ -332,7 +331,7 @@ # Check if we got a dataset object. croak("Not an Algorithm::DataSet") if(ref($x) ne "Algorithm::SVM::DataSet"); - return _predict_value($self->{svm}, $x); + return _predict_value($self, $x); } sub save { @@ -340,7 +339,7 @@ croak("Can't save model because no filename provided") if(! $file); - return _saveModel($self->{svm}, $file); + return _saveModel($self, $file); } sub load { @@ -348,13 +347,13 @@ croak("Can't load model because no filename provided") if(! $file); - return _loadModel($self->{svm}, $file); + return _loadModel($self, $file); } sub getNRClass { my ($self) = @_; - return _getNRClass($self->{svm}); + return _getNRClass($self); } sub getLabels { @@ -362,7 +361,7 @@ my $class = $self->getNRClass(); if($class) { - return _getLabels($self->{svm}, $class); + return _getLabels($self, $class); } return 0; @@ -371,13 +370,13 @@ sub getSVRProbability { my ($self) = @_; - return _getSVRProbability($self->{svm}); + return _getSVRProbability($self); } sub checkProbabilityModel { my ($self) = @_; - return _checkProbabilityModel($self->{svm}); + return _checkProbabilityModel($self); } sub train { @@ -386,7 +385,7 @@ croak("No training data provided") if(! @tset); # Delete the old training data. - _clearDataSet($self->{svm}); + _clearDataSet($self); # Ensure we've got the right format for the training data. for(@tset) { @@ -395,15 +394,15 @@ } # Train a new model. - _addDataSet($self->{svm}, $_) for(@tset); + _addDataSet($self, $_) for(@tset); - return _train($self->{svm}, 0); + return _train($self, 0); } sub retrain { my $self = shift; - return _train($self->{svm}, 1); + return _train($self, 1); } sub validate { @@ -412,7 +411,7 @@ $nfolds = 5 if(! defined($nfolds)); croak("NumFolds must be >= 2") if($nfolds < 2); - return _crossValidate($self->{svm}, $nfolds + 0); + return _crossValidate($self, $nfolds + 0); } sub svm_type { @@ -420,9 +419,9 @@ if(defined($type)) { croak("Invalid SVM type: $type") if(! exists($SVM_TYPES{$type})); - _setSVMType($self->{svm}, $SVM_TYPES{$type}); + _setSVMType($self, $SVM_TYPES{$type}); } else { - $SVM_TYPESR{_getSVMType($self->{svm})}; + $SVM_TYPESR{_getSVMType($self)}; } } @@ -431,51 +430,51 @@ if(defined($type)) { croak("Invalid kernel type: $type") if(! exists($KERNEL_TYPES{$type})); - _setKernelType($self->{svm}, $KERNEL_TYPES{$type}); + _setKernelType($self, $KERNEL_TYPES{$type}); } else { - $KERNEL_TYPESR{_getKernelType($self->{svm})}; + $KERNEL_TYPESR{_getKernelType($self)}; } } sub degree { my $self = shift; - (@_) ? _setDegree($self->{svm}, shift(@_) + 0) : _getDegree($self->{svm}); + (@_) ? _setDegree($self, shift(@_) + 0) : _getDegree($self); } sub gamma { my $self = shift; - (@_) ? _setGamma($self->{svm}, shift(@_) + 0) : _getGamma($self->{svm}); + (@_) ? _setGamma($self, shift(@_) + 0) : _getGamma($self); } sub coef0 { my $self = shift; - (@_) ? _setCoef0($self->{svm}, shift(@_) + 0) : _getCoef0($self->{svm}); + (@_) ? _setCoef0($self, shift(@_) + 0) : _getCoef0($self); } sub C { my $self = shift; - (@_) ? _setC($self->{svm}, shift(@_) + 0) : _getC($self->{svm}); + (@_) ? _setC($self, shift(@_) + 0) : _getC($self); } sub nu { my $self = shift; - (@_) ? _setNu($self->{svm}, shift(@_) + 0) : _getNu($self->{svm}); + (@_) ? _setNu($self, shift(@_) + 0) : _getNu($self); } sub epsilon { my $self = shift; - (@_) ? _setEpsilon($self->{svm}, shift(@_) + 0) : _getEpsilon($self->{svm}); + (@_) ? _setEpsilon($self, shift(@_) + 0) : _getEpsilon($self); } sub display { my $self = shift; - _dumpDataSet($self->{svm}); + _dumpDataSet($self); } 1;