【问题标题】:Memory usage of C++ program grows, (shown in Debian's "top"), until it crashesC++ 程序的内存使用量增长,(显示在 Debian 的“顶部”中),直到它崩溃
【发布时间】:2023-03-19 17:53:02
【问题描述】:

我正在开发一个应该能够运行几天的C++程序,所以它的内存消耗似乎增长得非常快有点麻烦。

程序的完整代码有点长,所以我将仅发布相关内容。结构如下:

int main (void){
//initialization of the global variables
error = 0;
state = 0;
cycle = 0;
exportcycle = 0;
status = 0;
counter_temp_ctrl = 0;
start = 0;
stop = 0;


inittimer();
mysql_del ("TempMeas");
mysql_del ("TempMeasHist");
mysql_del ("MyControl");
mysql_del ("MyStatus");
initmysql();



while(1){

    statemachine();

    pause();

    }

}

上面初始化的定时器函数如下:

void catch_alarm (int sig)
{
//Set the statemachine to state 1 (reading in new values)

    start = readmysql("MyStatus", "Start", 0);
    stop = readmysql("MyStatus", "Stop", 0);

       if (start == 1){
            state = 1;
      }
      if (stop == 1){
            state = 5;
      }


  //printf("Alarm event\n");
  signal (sig, catch_alarm);

  return void();
}

所以基本上,由于我没有在修改 MyStatus 选项卡的 web 界面中设置起始位,因此程序每秒只调用两次 readmysql 函数(计时器的间隔)。 readmysql函数如下:

float readmysql(string table, string row, int lastvalue){
float readdata = 0;

// Initialize a connection to MySQL
MYSQL_RES *mysql_res;
MYSQL_ROW mysqlrow;
MYSQL *con = mysql_init(NULL);
if(con == NULL)
{
error_exit(con);
}


if (mysql_real_connect(con, "localhost", "user1", "user1", "TempDB", 0, NULL, 0) == NULL)
{
error_exit(con);
}

if (lastvalue == 1){
    string qu = "Select "+ row +" from "+ table +" AS a where MeasTime=(select MAX(MeasTime) from "+ table;
    error = mysql_query(con, qu.c_str());
}
else{
    string qu = "Select "+ row +" from "+ table;
    error = mysql_query(con, qu.c_str());
}


mysql_res = mysql_store_result(con);

while((mysqlrow = mysql_fetch_row(mysql_res)) != NULL)
{
    readdata = atoi(mysqlrow[0]);
}

//cout << "readdata "+table+ " "+row+" = " << readdata << endl;

// Close the MySQL connection
mysql_close(con);

//delete mysql_res;
//delete mysqlrow;


return readdata;
}

我认为该函数中的变量存储在堆栈中,并在离开该函数时自动释放。然而,似乎内存的某些部分没有被释放,因为它毕竟只是增长。如您所见,我尝试对两个变量使用删除功能。好像没有效果。我在内存管理等方面做错了什么?

感谢您的帮助!

问候奥利弗。

【问题讨论】:

  • 你以某种方式泄漏了内存。也不需要!= NULL
  • 消除可疑线路,直到泄漏消失。
  • 我最近才开始重新磨练我的 C++ 技能,在 VBA 工作了很长一段时间后,最近在 C# 工作了更短的时间,所以我可能完全猜错了,但是...... error_exit()mysql_close() 释放“每秒两次”初始化的连接实例使用的内存?
  • 我想是这样,但我可能在这里错了。 Documentation of mysql_closeDocumentation of mysql_init 说“如果 mysql_init() 分配了一个新对象,则在调用 mysql_close() 以关闭连接时释放它。” error_exit 使用 mysql_close()。

标签: c++ mysql linux memory-management debian


【解决方案1】:

至少 mysql_store_result 正在泄漏。来自documentation

在调用 mysql_query() 或 mysql_real_query() 后,您必须为每个成功生成结果集的语句(SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE 等)调用 mysql_store_result() 或 mysql_use_result()。 您还必须在完成结果集后调用 mysql_free_result()。

【讨论】:

  • 谢谢!这很有帮助。我明天要测试这个,但这似乎至少是一个问题。
【解决方案2】:

如果您的程序持续消耗内存(从未释放它),那么您就有内存泄漏

检测内存泄漏的一个好方法是通过内存调试器运行它,例如valgrind:

$ valgrind /path/to/my/program

一旦你的程序开始消耗内存,停止它,valgrind 会给你一个很好的总结,告诉你你的程序在哪里分配了从未被释放的内存。

没有必要让系统内存不足而崩溃;等到它吃掉了一些尚未释放的内存。然后修复你的代码。然后重复直到不再检测到内存错误。

还要注意 valgrind 会拦截您的系统内存管理。这通常会导致(严重)性能损失。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-09
    • 2013-10-18
    • 2023-03-30
    • 1970-01-01
    相关资源
    最近更新 更多