Python Ctypes方法中的内存泄漏

Python Ctypes方法中的内存泄漏,python,c,memory-leaks,ctypes,Python,C,Memory Leaks,Ctypes,我有一个主要用Python编写的项目。这个项目运行在我的树莓皮(模型B)。使用Pi摄像机,我记录到一个流。每秒钟我都会对录音进行压缩,从流中取出最后一帧,并将其与旧帧进行比较。比较是用C代码完成的(主要是因为它比Python快) C代码是使用Ctypes从Python调用的。请参阅下面的代码 # Load picturecomparer.so and set argument and return types cmethod = ctypes.CDLL(Paths.CMODULE_LOCATIO

我有一个主要用Python编写的项目。这个项目运行在我的树莓皮(模型B)。使用Pi摄像机,我记录到一个流。每秒钟我都会对录音进行压缩,从流中取出最后一帧,并将其与旧帧进行比较。比较是用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]
必须比较的两个映像存储在磁盘上。Python将两个图像的路径作为C代码的参数。C代码将返回一个值(double),该值是两个图像百分比的差值

# 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;
}
#包括
#包括
#包括
#ifndef机顶盒映像的实现
#定义机顶盒映像的实现
#包括“stb_image.h”
#ifndef STBI_断言
#定义STBI_断言(x)
#恩迪夫
#恩迪夫
#定义颜色\u R 0
#定义颜色\u G 1
#定义颜色2
#定义偏移量10
双重比较图片(常量字符*路径1,常量字符*路径2);
双重比较图片(常量字符*路径1,常量字符*路径2)
{
双totalDiff=0.0,数值;
无符号整数x,y;
内部宽度1,高度1,组件1;
无符号字符*image1=stbi_加载(路径1,&width1,&height1,&comps1,0);
内部宽度2,高度2,组件2;
无符号字符*image2=stbi_加载(路径2、&width2、&height2、&comps2,0);
//执行一些检查以确保图像有效
如果(image1==NULL | image2==NULL){返回0;}
如果(width1!=width2 | height1!=height2){返回0;}
对于(y=0;y(OFFSET*-1)){value=0;}
totalDiff+=fabs(值)/255.0;
//以绿色计算差异
值=(int)图像1[(x+y*width1)*comps1+COLOR\u G]-(int)图像2[(x+y*width2)*comps2+COLOR\u G];
如果(值(OFFSET*-1)){value=0;}
totalDiff+=fabs(值)/255.0;
//用蓝色计算差异
值=(int)图像1[(x+y*width1)*组件1+颜色B]-(int)图像2[(x+y*width2)*组件2+颜色B];
如果(值(OFFSET*-1)){value=0;}
totalDiff+=fabs(值)/255.0;
}
}
总差=100.0*总差/(双倍)(宽1*高1*3);
返回totalDiff;
}
C代码将每~2秒执行一次。我刚刚注意到内存泄漏。大约10到15分钟后,我的树莓圆周率(Raspberry Pi)就剩下10MB的内存了。几分钟后,它崩溃,不再响应

我已经做了一些检查,以找出是什么原因导致了我的项目。如果我禁用C代码,我的整个项目将使用大约30-40MB的ram。这个项目是我所有的树莓皮必须执行

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

所以我的项目有大约300MB的内存

希望有人能告诉我哪里出了问题,或者如果我必须自己给GC打电话,等等

提前谢谢


p、 我知道图像比较不是最好的方法,但它现在对我很有效。

因为图像是作为指向缓冲区的指针返回的
stbi\u load
必须为它们分配空间,并且在返回之前您不会释放此空间,所以内存泄漏也就不足为奇了

检查文档,查看是否有特定的stpi_免费功能,或尝试添加
free(image1);免费(图片2)在最终返回之前


检查过之后,我可以明确地说,您应该免费拨打STBI_(image1);无STBI_(图2)返回之前。

我查看了stb_image.h,其中有一个函数stbi_image_free,可以释放stbi_load使用的内存。我现在运行我的项目15分钟,到目前为止只使用了~50MB。似乎再也提不起了。感谢您指出这一点。我假设在方法返回totalDiff值后,所有其他变量都会被GC自动“销毁”。@LittleOne-Python垃圾收集Python对象,而不是C对象,并且C在大多数系统上没有垃圾收集器。