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();
}
}
}
は、任意の助けてくれてありがとう。
*問題は、ターミナルのwatchコマンドでプログラムのメモリ使用量をチェックしたときです - あなたのC++プログラムが実際にメモリをリークするかどうかを判断するのにOSツールを使うべきではありません。さらに割り当てが必要な場合に備えて、C++ランタイムのヒープマネージャがメモリを保持している可能性があります。 「開始」ボタンを追加して、ベクターをもう一度書き込むときにメモリーが上昇し続けるかどうかを確認します。メモリが上がらない場合は、ヒープマネージャが設計どおりに動作しており、明らかなメモリリークがないことを確認します。 – PaulMcKenzie
スレッドをコンストラクタで起動するのではなく、起動するボタンを追加することを意味しますか? –
いいえ、私が言いたいことは、アプリケーションの起動と停止を繰り返してから、同じアプリケーションを再起動することです。実際にメモリがリークしているかどうかを判断するのは、2番目のスタートです。メモリの開始が最初の開始と同じ速度で増加することがわかったら、おそらくメモリリークのケースを作ることができます。このような増加が見られない場合は、ヒープマネージャーがその仕事をしていることを確認します。 – PaulMcKenzie