2016-10-12 6 views
1

QtベースのC++プログラムがあり、このプログラムは "STOP"ボタンをクリックするまでベクターにファイルを書き込むだけです。ファイルへの書き込み時にメモリ使用量が増加する

Qtデザイナーでは、プッシュボタンを押して、テキストを「STOP」に変更し、オブジェクトの名前を「button」にします。

問題は、端末のwatchコマンドでプログラムのメモリ使用量を確認すると、空きメモリが時間の経過と共に減少し、ボタンをクリックしても影響がないことがわかります。私がアプリケーションを閉じると、それはその初期に行くだけです。

test.pro:

#------------------------------------------------- 
# 
# Project created by QtCreator 2016-10-12T13:56:45 
# 
#------------------------------------------------- 

QT  += core gui 

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 

QMAKE_CXXFLAGS += -std=c++11 
QMAKE_CXXFLAGS += -D_GLIBCXX_USE_CXX11_ABI=0 
QMAKE_CXXFLAGS += -pthread 

TARGET = Test 
TEMPLATE = app 


SOURCES += main.cpp\ 
     mainwindow.cpp \ 
    writer.cpp 

HEADERS += mainwindow.h \ 
    writer.h 

FORMS += mainwindow.ui 

mainwindow.h:

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 

#include <QMainWindow> 

#include <writer.h> 

namespace Ui { 
class MainWindow; 
} 

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    explicit MainWindow(QWidget *parent = 0); 
    ~MainWindow(); 

private slots: 
    void on_stopButton_clicked(); 

    void on_startButton_clicked(); 

private: 
    Ui::MainWindow *ui; 
    writer *w; 
}; 

#endif // MAINWINDOW_H 

writer.h:

#ifndef WRITER_H 
#define WRITER_H 

#include <iostream> 
#include <fstream> 
#include <iterator> 
#include <string> 
#include <locale> 
#include <sstream> 
#include <thread> 
#include <atomic> 
#include <vector> 

#define COUNTER_FILENAME "data_counter.txt" 
#define DATA_PREFIX "data_no" 
#define DATA_EXTENSION ".csv" 

class writer 
{ 
public: 
    // For labeling 
    unsigned int label_id; 
    bool label; 
    // Start writing frame features in a file 
    void write(); 
    // Stop writing 
    void stopWriting(); 
    // Default demo constructor, sets up the frame thread which will process frame data in a seperate thread 
    explicit writer(); 
    // Default demo destructor, flags that the frame thread should stop and waits for the frame thread to join 
    ~writer(); 

protected: 
    std::unique_ptr<std::thread> frameThread; 
    std::atomic<bool> stopFrameThread; 
    std::vector<float> frameFeatures; 
    std::string data_filename; 
}; 

#endif // WRITER_H 

main.cppに:

#include "mainwindow.h" 
#include <QApplication> 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    MainWindow w; 
    w.show(); 

    return a.exec(); 
} 

mainwindow.cpp:

#include "mainwindow.h" 
#include "ui_mainwindow.h" 

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow), 
    w(new writer()) 
{ 
    ui->setupUi(this); 


} 

MainWindow::~MainWindow() 
{ 
    delete w; 
    delete ui; 
} 

void MainWindow::on_stopButton_clicked() 
{ 
    w->stopWriting(); 
} 

void MainWindow::on_startButton_clicked() 
{ 
    w->write(); 
} 

writer.cpp:

#include "writer.h" 

writer::writer() : 
    label_id(0), 
    label(false) 
{ 
    stopFrameThread = false; 
    // Resize the vector to put all frame features 
    frameFeatures.resize(1743, 0.0); 
} 

writer::~writer() 
{ 
    stopWriting(); 
} 

void writer::write() 
{ 
    // Setup the frame thread 
    stopFrameThread = false; 

    // Create a new thread to retrieve all features of each frame 
    frameThread = std::unique_ptr<std::thread>(new std::thread([ this ](){ 
     // Read from counter file to get counter value 
     std::string counter; 
     std::ifstream counter_in (COUNTER_FILENAME); 
     if(counter_in.is_open()){ 
      std::getline(counter_in, counter); 
      counter_in.close(); 
     }else{ 
      counter = "0"; 
     } 

     // Convert the counter into an integer 
     int c; 
     std::stringstream(counter) >> c; 

     // Compute data filename 
     data_filename = DATA_PREFIX + counter + "_id" + applicant_id + DATA_EXTENSION; 

     std::ofstream data_file(data_filename); 

     if(data_file.is_open()){ 
      // Start the main processing loop 
      while(! stopFrameThread){ 
       for(int index = 0; index < 1743; index++){ 
        frameFeatures[ index ] = index; 
       } 

       for(std::vector<float>::iterator it = frameFeatures.begin(); it != frameFeatures.end(); ++it){ 
        data_file << " " + std::to_string(*it); 
       } 
       data_file << "\n"; 
      } 

      // Close the data file 
      data_file.close(); 

      // Write incremented counter value on counter file 
      std::ofstream counter_out (COUNTER_FILENAME); 
      if(counter_out.is_open()){ 
       counter_out << ++c; 
       counter_out.close(); 
      }else{ 
       std::cerr << "Unable to write on counter file\n"; 
      } 
     }else{ 
      std::cerr << "Unable to open the data file\n"; 
     } 
    })); 
} 

void writer::stopWriting() 
{ 
    // Flag that the frame thread should stop 
    stopFrameThread = true; 

    // Wait for the frame thread to stop 
    if(frameThread){ 
     if(frameThread->joinable()){ 
      frameThread->join(); 
     } 
    } 
} 

は、任意の助けてくれてありがとう。

+1

*問題は、ターミナルのwatchコマンドでプログラムのメモリ使用量をチェックしたときです - あなたのC++プログラムが実際にメモリをリークするかどうかを判断するのにOSツールを使うべきではありません。さらに割り当てが必要な場合に備えて、C++ランタイムのヒープマネージャがメモリを保持している可能性があります。 「開始」ボタンを追加して、ベクターをもう一度書き込むときにメモリーが上昇し続けるかどうかを確認します。メモリが上がらない場合は、ヒープマネージャが設計どおりに動作しており、明らかなメモリリークがないことを確認します。 – PaulMcKenzie

+0

スレッドをコンストラクタで起動するのではなく、起動するボタンを追加することを意味しますか? –

+0

いいえ、私が言いたいことは、アプリケーションの起動と停止を繰り返してから、同じアプリケーションを再起動することです。実際にメモリがリークしているかどうかを判断するのは、2番目のスタートです。メモリの開始が最初の開始と同じ速度で増加することがわかったら、おそらくメモリリークのケースを作ることができます。このような増加が見られない場合は、ヒープマネージャーがその仕事をしていることを確認します。 – PaulMcKenzie

答えて

0

私は問題を修正してからしばらくしていますが、誰かが同様の問題に遭遇した場合に備えてここに書き込むべきだと思っていました。

コードにバグもメモリリークもありませんでした。プログラムは完璧に動作します。問題は、新しいベクトルを作成するプロセスが、ファイルに書き込むプロセスよりも速いことでした。

私はプロセスをスピードアップするために2つの別々のスレッドを持つことでそれを解決しました。最初のスレッドはベクトルを作成し、バッファに格納します。 2番目のスレッドはそのバッファからベクトルを取り出して書き込みます。

関連する問題