2014年1月7日火曜日

MacとLinuxの挙動の違いについて

昨日ポストした,mac上で作ったGtk+を使って計算するプログラムを,Linuxでも動かそうと思ってコンパイルしてみました.
プラットフォームに依存することはしていないので完全に互換のはず,と思って単純にコンパイルだけしました.

しかし,コンパイラではerrorもwarningも出なかったのですが,実行してみたらセグメンテーション違反になってしまう.
がっくりきて小一時間いろいろ試したら,動くようになりました.

理由が二つありました.


  1. パイプを使ってgnuplotを開くときのパスの指定の仕方
  2. ファイルオープンが失敗したときにfcloseするべきかどうか


前者は,mac上ではgnuplotにパスが通っていれば,

FILE *gp;
gp = popen("gnuplot", "w");

で動いたのですが,Linuxでは

FILE *gp;
gp = popen("/usr/bin/gnuplot", "w");

としないと動きません.
これはすぐに分かったのですが,問題は次のファイルオープンが失敗した時の処理です.

計算し終わったデータを格納するファイルが,同じファイル名で既に存在する場合,基本的にはアペンドモードで追記しているので問題ないのですが,念のため以下のように確認するダイアログを出していました.

  if((fp = fopen (filename, "r")) == NULL){
    fclose(fp);
    start_or_stop=1;
  }
  else{
  fclose(fp);
  GtkWidget *dialog;
  GtkWidget *parent;
  GtkWidget *labeld;
  gint response;
.
.
.
(以下にダイアログを出すコードが続きます.)
これは単純にファイルが存在するかどうかを確認するために付け加えたコードでした.
以前,c言語ではファイルのオープンに失敗しても,そのポインタにNULLが格納されて,以後書き込む時にNULLに書き込んでしまい危険だから云々...
と勉強した記憶があったので,fcloseを書いていました.

macではこれで実行しても問題ないし,linuxでもコンパイラではerrorもwarningも出なかったのですが,実行すると無情のセグメンテーション違反とのお答えが..

おかしい場所はここしかないと思ったので,fpがNULLのときのfcloseをコメントアウトすると,無事に動きました.

なぜでしょう??

0 件のコメント:

コメントを投稿