2016-10-12 6 views
1

У меня есть небольшая программа на C++ на основе Qt, и эта программа просто записывает вектор в файл, пока я не нажму кнопку «STOP».Использование памяти увеличивается со временем при записи в файл

В дизайнере Qt я просто нажму кнопку, измените текст на «STOP» и назовите объект «кнопка».

Проблема в том, что когда я проверяю использование памяти программой командой 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++ теряет память. Менеджер кучи времени выполнения C++ может удерживать память в случае необходимости дополнительных распределений. Добавьте кнопку «Пуск» и посмотрите, продолжает ли память продолжать работу, когда вы снова пишете вектор. Если память не поднимается, это подтверждает, что диспетчер кучи работает как сконструированный, и нет очевидной утечки памяти. – PaulMcKenzie

+0

Вы имеете в виду добавить кнопку, чтобы начать тему, а не запускать ее с помощью конструктора? –

+0

Нет, я намекаю на то, чтобы начать, остановить, а затем начать снова в том же запуске вашего приложения. Это второй старт, который определит, действительно ли вы утечка памяти. Если вы видите, что начало записи памяти увеличивается с той же скоростью, что и начальный старт, то вы, вероятно, можете сделать это для утечки памяти. Если вы не видите такого увеличения, то это подтверждает, что менеджер кучи выполняет свою работу. – PaulMcKenzie

ответ

0

Прошло некоторое время с тех пор, как я исправил проблему, но я подумал, что должен написать ее здесь, если кто-то столкнется с аналогичной проблемой.

В коде не было ошибок и утечек памяти. Программа отлично работает. Проблема заключалась в том, что процесс создания новых векторов был быстрее, чем процесс записи в файл.

Я решил это, имея два отдельных потока, чтобы ускорить процесс. Первый поток создал векторы и сохранил их в буфере. Второй поток возьмет вектор из этого буфера и напишет его.

Смежные вопросы