pipe&forkのメモリリーク?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
chibago

pipe&forkのメモリリーク?

#1

投稿記事 by chibago » 13年前

皆様、ご無沙汰しております。
chibagoです。

以前、こちらでお世話になって完成させたpipe&forkを用いた
標準入出力をpipeして外部プログラムを制御しこまごまとした
ジョブを大量にこなしておりました。

しかし、あるとき突然forkに失敗しました。
特に、それだけが大きなジョブというわけではなく、
止まった場所からリスタートさせてみると問題なく動きました。

ネットで見た限りでは、仮想メモリが少なくなるとfork
に失敗するとのことでした。状況的にも私のケースは
これに当てはまるのではないかと思われます。

メモリリークが発生した場合にプログラムを止めることなく
リフレッシュすることは可能でしょうか。

そもそも、この現象はメモリリークで起こっているのでしょうか。
(他の可能性がございましたらご指摘いただければ幸いです。)

ちなみに、動かしているプログラムは以下の様なものです。

コード:

PipeToStandardIO::PipeToStandardIO(const std::string command){
  int pid;
  if((pid = this->generate_pipe(command)) == 0){
    std::cout<<"Cannot generate pipe"<<std::endl;
    exit(-1);
  }
  this->open_stream();
}

PipeToStandardIO::~PipeToStandardIO(){
  if (this->read_stream_status != "closed")
    this->close_standard_output();
  if (this->write_stream_status != "closed")
    this->close_standard_input();
}

  void PipeToStandardIO::set_standard_input(const std::string& str){
    fputs(str.c_str(), this->write_stream); 
}

  std::string PipeToStandardIO::get_standard_output(){
    std::ostringstream os;
    char buf[1000];
    while(fgets(buf, 1000, this->read_stream) !=NULL){
      os << buf;    
    } 
    return os.str();
}

void PipeToStandardIO::close_standard_output(){
  if (this->read_stream_status != "closed")
      fclose(this->read_stream);
  this->read_stream_status = "closed";
}

void PipeToStandardIO::close_standard_input(){
  if (this->write_stream_status != "closed")
       fclose(this->write_stream);
  this->write_stream_status = "closed";
}

int PipeToStandardIO::generate_pipe(const std::string command){
  int pipe_c2p[2], pipe_p2c[2];
  int pid;

  /* Create two pipes. */
  if(pipe(pipe_c2p)<0){
    std::cout<<"Cannot create a pipe of child to parent."<<std::endl;
    return -1;
  }
  if(pipe(pipe_p2c)<0){
    std::cout<<"Cannot create a pipe of parent to child."<<std::endl;
    close(pipe_c2p[0]);
    close(pipe_c2p[1]);
    return -1;
  }

  /* Invoke processs */
  if((pid = fork()) < 0 ){
    std::cout<<"Cannot invoke processs."<<std::endl;
    close(pipe_c2p[0]);
    close(pipe_c2p[1]);
    close(pipe_p2c[0]);
    close(pipe_p2c[1]);
    return -1;
  }

  /* Implimentation of child. */
  if(pid == 0){
    close(pipe_p2c[1]);
    close(pipe_c2p[0]);
    dup2(pipe_p2c[0], 0);
    dup2(pipe_c2p[1], 1);
    close(pipe_p2c[0]);
    close(pipe_c2p[1]);
    if (execlp("sh", "sh", "-c", command.c_str(), NULL) < 0){
    std::cout<<"Cannot invoke child processs."<<std::endl;
    close(pipe_p2c[0]);
    close(pipe_c2p[1]);
    exit(1);
    }
  }

  close(pipe_p2c[0]);
  close(pipe_c2p[1]);
  this->fd_w = pipe_p2c[1];
  this->fd_r = pipe_c2p[0];
  return pid;

  }

void PipeToStandardIO::open_stream(){
  this->read_stream = fdopen(this->fd_r, "r");
  if (this->read_stream == NULL){
    std::cout<<"Cannot establish a read stream."<<std::endl;
    exit(-1);
  }

  this->write_stream = fdopen(this->fd_w, "w");
  if (this->write_stream == NULL){
    std::cout<<"Cannot establish a write stream."<<std::endl;
    exit(-1);
  }
}



アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: pipe&forkのメモリリーク?

#2

投稿記事 by softya(ソフト屋) » 13年前

そもそもメモリリークは管理から取り残されたメモリのことですから、それがある事自体が問題です。
メモリリークではなく管理されていてメモリが足らないのなら省メモリを実現せねばなりません。
メモリリークしているメモリを解放する方法はありませんが、管理しているメモリなら必要に応じて解放できるはずです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

chibago

Re: pipe&forkのメモリリーク?

#3

投稿記事 by chibago » 13年前

softya様、
お返事ありがとうございます。

余り理解しておらず用語をもちいておりますので、
「メモリリーク」は不適切だったようです。

一方で、管理されているメモリですが、特に、並列利用はしておりませんので、
使用に応じてメモリ使用量が蓄積するとは考えにくいです。

基本的に、提示したプログラムをその都度呼び出している
だけで、特にポインタも使っておりませんので、
その都度全メモリが解放されてから次のジョブに行っているはずです。

どのような対応を取ればよろしいでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: pipe&forkのメモリリーク?

#4

投稿記事 by softya(ソフト屋) » 13年前

OSの記載がないのですがLinux/Unix系だと思います。
私もforkには詳しくないので(pthread系しか使ったことがない)
無闇にforkしていませんでしょうか?
プロセスの完了とか、ちゃんとやっていますか?

「Man page of PIPE」 参考。
http://linuxjm.sourceforge.jp/html/LDP_ ... ipe.2.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Poco
記事: 161
登録日時: 15年前

Re: pipe&forkのメモリリーク?

#5

投稿記事 by Poco » 13年前

システムコールで失敗しているのがわかっているのであれば、
errnoとstrerror()で原因が分かると思います。

chibago

Re: pipe&forkのメモリリーク?

#6

投稿記事 by chibago » 13年前

Poco様、
お返事ありがとうございました。
ご指摘の点気付きませんでした。
今回の件は必ずしも再現性のある不具合ではありませんので
とりあえず、strerrorを実装してみて、同様の不具合が発生し原因が特定できた
時点で改めてご相談させていただきたいと思います。

閉鎖

“C言語何でも質問掲示板” へ戻る