关于sqlite3使用操作中内存耗尽导致进程被kill的问题

    最近由于项目的需要,在cortex-A8板子上开发一个关于分容柜控制的程序。需要用网络与上位机通讯。由于检测需要用到脱机工作。保存至少1440*150条数据,所以引进了sqlite数据库。移植了一个sqlite3动态库进行。发现程序跑到了两小时以上,外界的LCD操作会变得缓慢,网络上接收到的数据也是时有时无。然后一段时间发现程序崩溃了。信息显示的是程序过大,被杀死。这个问题也是找了挺久,一直以为是别的地方内存操作不当引起的内存泄漏。后来慢慢排查,发现是操作sqlite不当引起的。

    百度上寻找原因,很多是操作sqlite是将数据库直接打开,然后放进系统内存中,这样子会使得增删改查的速度变得快一点。所以如果每次打开操作数据库没有释放掉相应的内存,就会导致内存不断的增加。但是我发现,如果你是频繁的打开数据库,操作,关闭数据库,如果开启了事务操作,是会出现数据写不进去的。虽然内存增加的问题解决了,但是会引出新的问题,数据保存补了。所以不能只靠简单的打开关闭操作数据库来解决。

    后来又找了几个方法,比较有效的是。我当时在查找数据库中是否存在数据的时候定义了一个指针sqlite3_stmt *stmt = NULL;然后用到了sqlite3_prepare_v2(db, sql_cmd_global, -1, &stmt, NULL) 这条函数进行查找,发现这是一条准备执行的语句。返回的结果没有释放会一直存在。后来我换了条语句 sqlite3_get_table(db, sql_cmd_global, &azResult, &h, &l, &errmsg);,其中定义了另一个指针char **azResult;。这样子返回结果会存放在这个指针,并且在操作结束后,手动释放掉这,用的函数是这个 sqlite3_free_table(azResult); sqlite3_free(errmsg); 发现在操作过程中不会增加运行内存。

    但是问题并没有就这样子解决,因为需要定时插入数据,所以还是会产生多余的内存在系统中。但是我发现我已经释放掉过程中的数据了。后来发现不要将数据库放在根目录下。就不会再插入操作中很快的产生内存。(这点到现在还是不很明白,有大佬可以解释下吗?放下别的目录下不会增加内存,程序的根目录就会)。然后我挂机了一天,发现内存还是会慢慢增加,不过很慢就是了而且每次运行数据,上一次的还是会在。这时候,我就想到,可能是过程垃圾,就用命令前行清理掉这些内存了。问题虽然得到短暂的解决,但是我还是没有真正的解决掉这个问题,希望有相似经历的大佬,可以交流一下,下面附上查看内存的函数和清理内存的命令。

查看内存

int cat_mmp()
{
    struct sysinfo s_info;
    int error;

    error = sysinfo(&s_info);
    printf("Uptime = %ds\n\n" "RAM: total %lu used = %lu, free = %lu\n",
           s_info.uptime,
           s_info.totalram/1024,(s_info.totalram/1024-s_info.freeram/1024),s_info.freeram/1024);
    return 0;
}


记得包含头文件#include <linux/unistd.h>     /* 包含调用 _syscallX 宏等相关信息*/
#include <linux/kernel.h>     /* 包含sysinfo结构体信息*/


清理内存的命令

echo 3 > /proc/sys/vm/drop_caches

猜你喜欢

转载自blog.csdn.net/jutun5887/article/details/78958295
今日推荐