oneiric / vld

Visual Leak Detector for Visual C++ 2019
GNU Lesser General Public License v2.1
112 stars 35 forks source link

Failed to detect memory leak in Win32 mode when using OpenCV's imshow and waitKey #6

Closed zchrissirhcz closed 3 years ago

zchrissirhcz commented 3 years ago

Tested on VS2017 with Win32 and X64 mode. vld version is 2.6.0. VS2017 version is 15.9.27. X64 mode reports memory leak. Win32 mode doesn't report memory leak.

Reproduceable code: (What this code does is: read a text that contains image names, then read each rgb image, resize to 256x256, and show them in window, finally call a function that does contain an memory leak, and expect VLD report memory leaks):

#include <vld.h>

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

#include <string>
#include <vector>
#include <opencv2/opencv.hpp>

void leak_test2()
{
    int len = 100;
    int size = len * sizeof(int);
    int* data = (int*)malloc(size);
    data[0] = 100;
    data[200] = 3;
}

static void read_txt_line_by_line(const char* path, std::vector<std::string>& image_paths)
{
    FILE* fin = fopen(path, "r");
    if (fin == NULL) {
        fprintf(stderr, "failed to open %s\n", path);
        exit(-1);
    }
    char line[1024];
    void* ret;
    while (true) {
        memset(line, 0, sizeof(line));
        ret = fgets(line, sizeof(line), fin);
        if (ret == NULL) break;
        if (line[strlen(line) - 1] == '\n' || line[strlen(line) - 1] == '\r') {
            line[strlen(line) - 1] = '\0';
        }
        if (line[strlen(line) - 1] == '\r' || line[strlen(line) - 1] == '\n') {
            line[strlen(line) - 1] = '\0';
        }
        //printf("%s\n", line);
        image_paths.push_back(line);
    }
    fclose(fin);
}

static void rgb_bgr_swap(unsigned char* data, int h, int w)
{
    int len = h * w * 3;
    for (int i = 0; i < len; i += 3) {
        unsigned char t = data[i];
        data[i] = data[i + 2];
        data[i + 2] = t;
    }
}

static void leak_test_()
{
    int h = 256; // height
    int w = 256; // width
    int c = 3;   // channel
    int len = h * w*c;
    size_t buf_size = len * sizeof(unsigned char);
    unsigned char* data = (unsigned char*)malloc(buf_size); // image buffer
    unsigned char* ptr = data;
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < 256; j++) {
            *ptr++ = (unsigned char)j;    /* R */
            *ptr++ = (unsigned char)i;    /* G */
            *ptr++ = 128;                 /* B */
        }
    }

    rgb_bgr_swap(data, h, w);
    cv::Mat result(h, w, CV_8UC3, data);
    cv::imwrite("result.jpg", result);

    // [step2]
    //free(data);  //here, we make an memory leak
}

void leak_test_imshow()
{
    std::string data_dir = "E:/data/VOC2007";
    std::string im_dir = "E:/data/VOC2007/JPEGImages";
    std::string txt_pth = "E:/data/VOC2007/lite+.txt";

    std::vector<std::string> image_paths;
    read_txt_line_by_line(txt_pth.c_str(), image_paths);

    //cv::namedWindow("image");
    for (int i = 0; i < image_paths.size(); i++) {
        if (i > 10) break;
        image_paths[i] = im_dir + "/" + image_paths[i];
        printf("image_paths[i]=%s\n", image_paths[i].c_str());
        cv::Mat image = cv::imread(image_paths[i]);
        cv::resize(image, image, cv::Size(256, 256));
        cv::imshow("image", image);
        cv::waitKey(100);
    }

    leak_test_();

}

int main()
{
    printf("--- begin leak test\n");
    //leak_test2();
    leak_test_imshow();
    printf("--- end   leak test\n");

    return 0;
}

Running result: vld_imshow_x64_win32

zchrissirhcz commented 3 years ago

Figured out that Win32 mode still can give VLD output, by adding this line in the very last of main() function:

VLDReportLeaks();
oneiric commented 3 years ago

Since VLD can work, I will close this issue.