Ctypes 方法中的内存泄漏

Memory Leak in Ctypes method

我有一个主要用 Python 编写的项目。该项目在我的 Raspberry Pi(模型 B)上运行。我使用 Pi Camera 录制到流中。每一秒我都会暂停录制以从流中获取最后一帧并将其与旧帧进行比较。比较是在 C 代码中完成的(主要是因为它比 Python 快)。

C 代码是使用 Ctypes 从 Python 调用的。请参阅下面的代码。

# Load picturecomparer.so and set argument and return types
cmethod = ctypes.CDLL(Paths.CMODULE_LOCATION)
cmethod.compare_pictures.restype = ctypes.c_double
cmethod.compare_pictures.argtypes = [ctypes.c_char_p, types.c_char_p]

必须比较的2张图像存储在磁盘上。 Python 将两个图像的路径作为 C 代码的参数。 C 代码将 return 一个值(双精度),这是两个图像的百分比差异。

# Call the C method to compare the images
difflevel = cmethod.compare_pictures(path1, path2)

C 代码如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#ifndef STB_IMAGE_IMPLEMENTATION
    #define STB_IMAGE_IMPLEMENTATION
    #include "stb_image.h"

    #ifndef STBI_ASSERT
        #define STBI_ASSERT(x)
    #endif
#endif

#define COLOR_R 0
#define COLOR_G 1
#define COLOR_B 2
#define OFFSET 10

double compare_pictures(const char* path1, const char* path2);

double compare_pictures(const char* path1, const char* path2)
{
    double totalDiff = 0.0, value;
    unsigned int x, y;

    int width1, height1, comps1;
    unsigned char * image1 = stbi_load(path1, &width1, &height1, &comps1, 0);

    int width2, height2, comps2;
    unsigned char * image2 = stbi_load(path2, &width2, &height2, &comps2, 0);

    // Perform some checks to be sure images are valid
    if (image1 == NULL | image2 == NULL) { return 0; }
    if (width1 != width2 | height1 != height2) { return 0; }

    for (y = 0; y < height1; y++)
    {
        for (x = 0; x < width1; x++)
        {
            // Calculate difference in RED 
            value = (int)image1[(x + y*width1) * comps1 + COLOR_R] - (int)image2[(x + y*width2) * comps2 + COLOR_R];
            if (value < OFFSET && value > (OFFSET * -1)) { value = 0; }
            totalDiff += fabs(value) / 255.0;

            // Calculate difference in GREEN 
            value = (int)image1[(x + y*width1) * comps1 + COLOR_G] - (int)image2[(x + y*width2) * comps2 + COLOR_G];
            if (value < OFFSET && value >(OFFSET * -1)) { value = 0; }
            totalDiff += fabs(value) / 255.0;

            // Calculate difference in BLUE
            value = (int)image1[(x + y*width1) * comps1 + COLOR_B] - (int)image2[(x + y*width2) * comps2 + COLOR_B];
            if (value < OFFSET && value >(OFFSET * -1)) { value = 0; }
            totalDiff += fabs(value) / 255.0;
        }
    }
    totalDiff = 100.0 * totalDiff / (double)(width1 * height1 * 3);
    return totalDiff;
}

C 代码将每 ~2 秒执行一次。我刚刚注意到存在内存泄漏。大约 10 到 15 分钟后,我的 Raspberry Pi 剩下大约 10MB 的内存可供使用。几分钟后它崩溃并且不再响应。

我已经做了一些检查以找出导致我的项目出现这种情况的原因。如果我禁用 C 代码,我的整个项目使用大约 30-40MB 内存。这个项目是我 Raspberry Pi 必须执行的全部。

B 型:512MB 内存,在 CPU 和 GPU 之间共享。 GPU:128MB (/boot/config.txt)。 我的 Linux 发行版使用:~60MB。

所以我的项目有大约 300MB。

希望有人能指出我哪里出错了,或者我是否必须自己调用 GC,等等。

提前致谢。

p.s。我知道图像比较不是最好的方法,但现在对我有用

由于图像被 return 编辑为指向缓冲区的指针 stbi_load 必须为它们分配 space 并且您不会在 return 之前释放此 space =]所以内存泄漏并不奇怪。

查看文档以查看是否有特定的 stpi_free 函数或尝试在最后的 return.

之前添加 free(image1); free(image2);

经过检查,我可以断然地说你应该在 returning 之前调用 STBI_FREE(image1); STBI_FREE(image2);