Skip to content

Cocoa/highgui: fix leak in cvGetWindowRect_COCOA#26625

Merged
asmorkalov merged 1 commit intoopencv:4.xfrom
NekoAsakura:4.x
Dec 20, 2024
Merged

Cocoa/highgui: fix leak in cvGetWindowRect_COCOA#26625
asmorkalov merged 1 commit intoopencv:4.xfrom
NekoAsakura:4.x

Conversation

@NekoAsakura
Copy link
Copy Markdown
Contributor

#26574 reported a memory leak occurring when calling getWindowImageRect on macOS. After investigation, it was found that the leak was caused by the cvGetWindowRect_COCOA, which created several NSObject instances without setting up a local autorelease pool.

NSRect rect = [window frame];
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6
NSPoint pt = [window convertRectToScreen:rect].origin;
#else
NSPoint pt = [window convertBaseToScreen:rect.origin];
#endif
NSSize sz = [[[window contentView] image] size];

The patch has been compiled and tested on macOS 15.1.1, confirming that the bug is resolved.

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
  • The PR is proposed to the proper branch
  • There is a reference to the original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

Copy link
Copy Markdown
Contributor

@VadimLevin VadimLevin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on the following setup:

cpu: x86_64
macOS 15.2
Xcode 16.2

Requirements:

pip install --require-virtualenv psutil matplotlib

Code for testing:

import os

import cv2
import matplotlib.pyplot as plt
import numpy as np
import psutil


NUM_ITERATIONS = 1000


def plot_memory_usage(memory_usage):
    plt.figure(figsize=(10, 5))
    x = np.arange(len(memory_usage))
    plt.plot(x, memory_usage, label="Memory Usage (KB)", color="blue")
    plt.title("Memory Usage Over Time")
    plt.xlabel("Iterations")
    plt.ylabel("Memory Usage (KB)")
    plt.legend()
    plt.grid()
    plt.savefig("test_opencv_memory_leak.png")


def main():
    process = psutil.Process(os.getpid())

    shape = (800, 600, 3)
    image = np.random.randint(0, 255 + 1, np.prod(shape), np.uint8).reshape(shape)
    memory_usage = np.zeros(NUM_ITERATIONS, dtype=np.float32)

    cv2.namedWindow("image", cv2.WINDOW_NORMAL)
    for i in range(NUM_ITERATIONS):
        rect = cv2.getWindowImageRect("image")

        cv2.imshow("image", image)

        memory_usage[i] = process.memory_info().rss / 1024

        if cv2.waitKey(1) == ord("q"):
            break

    print("Current memory:", memory_usage[-1], "KB")
    print("Peak memory usage:", np.max(memory_usage), "KB")

    plot_memory_usage(memory_usage)


if __name__ == "__main__":
    main()

Memory usage without fix
test_opencv_memory_leak_without_fix

Current memory: 2154040.0 KB
Peak memory usage: 3587704.0 KB

I think, the drop in memory usage corresponds to time when ARC kicks in.

Memory usage with fix
test_opencv_memory_leak_with_fix

Current memory: 92292.0 KB
Peak memory usage: 92292.0 KB

@NekoAsakura
Copy link
Copy Markdown
Contributor Author

I have revised my commit to use @autoreleasepool.

Memory usage with fix
test_opencv_memory_leak

@asmorkalov asmorkalov added this to the 4.11.0 milestone Dec 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants