Unknown Region

プログラムでハマったエラーとその解決方法についての備忘録メモ

【Java】プリミティブのMax値とMin値にご注意を

以下のようなプログラムがあったとして、Step1、Step2、Step3でvalueとして何が出力されるかという問題。

大抵のエンジニアは、何がしたいかピンと来ると思います。

例: Demo.java

public class Demo {

	public static void main(String... args) {

		long value = Long.MAX_VALUE;

		System.out.println("step1: value = " + value);

		value++;

		System.out.println("step2: value = " + value);

		value++;

		System.out.println("step3: value = " + value);

	}

}

結果:

step1: value = 9223372036854775807

step2: value = -9223372036854775808

step3: value = -9223372036854775807

そう、整数オーバーフローが起きています。

これはLongの最大値である9223372036854775807を超えてしまったので、有効桁数を超えて符号がおかしくなってしまいました。

明らかに異常事態なのですが、困ったことにJavaはこれに対して例外を投げてくれません。

Java8以降を使用している場合、このプログラムに限った話で言えばMath.incrementExact(long a)を使えば解決します。

これは、引数の値がLong.MAX_VALUEと同値だった場合に例外を発生させるメソッドです。

今回の場合は単純に1をインクリメントしているので良いのですが、2以上の数値を加算して問題が起きることの方が多いと思いますね。

問題が起きうるのであれば、計算前にしっかりと値のチェックを行う必要がありそうです。

(例えばLong.MAX_VALUEから加算対象の数値2つを減算して、0を下回ることを確認するなど)

またオーバーフローと同様に、アンダーフローについても考えておく必要がありますね。

 

【Perl】FindBinを使う

以下はファイルの一覧を出力するプログラムです。

用途としては、このプログラムと同階層にあるファイルの一覧を出力したいとします。

プログラム例1(/tmp/example/hoge.pl) :

#/usr/bin/perl
  
use strict;
use warnings;
use utf8;

my @files = glob("./*");
foreach my $file (@files) {
  print($file);
  print("\n");
}

このプログラムには問題があります。

このプログラム内では相対パスを使用しているので、プログラムをどこから実行したかを考慮しなければいけません。

プログラムと同階層のファイル一覧を取得したいのに、実行した場所にあるファイル一覧が取得されてしまいますね。

 

解決方法としては、相対パスをやめて絶対パスを使うのが一番確実です。

でも配置場所が明確に決まっていないために絶対パスを記載するわけには行かないという場合も存在しますよね?

そういう時に便利なのが「FindBin」というモジュール。

これは、プログラム自体のパスを見つけてくれるものです。

先ほどのプログラムを以下の様に修正します。

プログラム例2(/tmp/example/fuga.pl) :

#/usr/bin/perl
  
use strict;
use warnings;
use utf8;
use FindBin;

my @files = glob($FindBin::Bin."/*");
foreach my $file (@files) {
  print($file);
  print("\n");
}

これでプログラムと同階層にあるファイルとディレクトリの一覧が取得できます。

ただこちらの場合は例1とは違い、出力されるファイル一覧も絶対パスになっているのでそれだけは注意しましょう。

主に設定ファイルやテンプレートファイルなどをプログラムと同階層に置きたい場合などに使えますよ!

 

連絡先: plugout777★yahoo.co.jp (クローラー対策のため★を@に変更してください)