Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Memory Leak Caused by Frequent Dynamic Creation/Destruction of QML Windows in Qt 5.15.19 on Windows
Forum Updated to NodeBB v4.3 + New Features

Memory Leak Caused by Frequent Dynamic Creation/Destruction of QML Windows in Qt 5.15.19 on Windows

Scheduled Pinned Locked Moved Unsolved General and Desktop
2 Posts 2 Posters 59 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    jason1122
    wrote last edited by jason1122
    #1

    Hello everyone,

    I am encountering a significant memory leak when repeatedly creating and destroying Window components (using QML) in a Qt 5.15.19 application on Windows. The issue appears to be related to unreleased shared resources. I would greatly appreciate any help or insight you can provide.


    Environment for Reproduction

    • OS: Windows 10 (running in a VMware virtual machine)
    • Qt Version: 5.15.19
    • Application Type: Qt Quick (QML)
    • Compiler/Architecture: The test program is compiled as a 32-bit application. (MSVC 2022, 32-bit)

    Minimal Reproducible Test Code

    The issue can be observed by running the following two QML files. The Timer in main.qml continuously creates and destroys a new SessionWin instance every second.

    main.qml

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Controls 2.12
    
    Window {
        id: id_main_win
        visible: true
        width: 1280
        height: 720
        color: "blue"
    
        property int createCount: 0
    
        Text {
            anchors.centerIn: parent
            text: createCount
            font.pixelSize: 30
        }
    
        Button {
            id: top_right_button
            width: 200
            height: 40
            font.pixelSize: 16
            text: "stop"
    
            anchors {
                top: parent.top
                right: parent.right
            }
    
            onClicked: {
                console.info(`stop createSession timer, createCount ${createCount}`)
                id_timer.stop()
                if (id_timer.tmpwin) {
                    id_timer.tmpwin.destroy()
                    id_timer.tmpwin = null
                }
            }
            background: Rectangle {
                color: top_right_button.hovered ? "#e0e0e0" : "red"
                radius: 5
            }
        }
    
        Button {
            id: top_left_button
            width: 200
            height: 40
            font.pixelSize: 16
            text: "restart"
    
            anchors {
                top: parent.top
                left: parent.left
            }
    
            onClicked: {
                console.info("restart createSession timer")
                id_timer.restart()
    
            }
            background: Rectangle {
                color: top_left_button.hovered ? "#e0e0e0" : "red"
                radius: 5
            }
        }
    
        Timer {
            id: id_timer
            repeat: true
            interval: 1000 // Creates and destroys a window every second
            property var tmpwin: null
            onTriggered: {
                if (tmpwin) {
                    tmpwin.destroy()
                    tmpwin = null
                }
    
                tmpwin = createSession()
            }
        }
    
        Component {
            id: id_sess
            SessionWin {
            }
        }
    
        function createSession() {
            var win = id_sess.createObject(id_main_win)
            createCount += 1
            return win
        }
    }
    

    SessionWin.qml

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Controls 2.12
    
    Window {
        id: id_session_win
        width: 1024
        height: 1024
        visible: true
    
        Component.onCompleted: {
            console.debug(`memoryTracer: create object: ${this}, size: ${width}x${height}`)
        }
    
        Component.onDestruction: {
            console.debug(`memoryTracer: destroy object: ${this}`)
        }
    }
    

    Preliminary Analysis Findings

    1. Shared Memory Accumulation: The process's shared memory usage continuously increases over time.
      • Using the vmmap.exe tool to examine the process's virtual address space, I found that each creation/destruction cycle leaves behind a shared memory block of approximately 4320 KB.
      • For instance, if I repeat the create/destroy cycle 80 times, there will be 80 unreleased shared memory blocks of 4320 KB each.
    2. Shared GPU Resource: When the test program is run on a physical machine (instead of a VM), the leaked memory region is identified as being related to Shared GPU resources. This suggests an unreleased graphics/window resource.

    I suspect this may be a bug related to how Qt 5.15.19 handles the cleanup of platform-specific resources (possibly related to the windowing system or graphics backend) when a QML Window is dynamically destroyed.

    Has anyone else experienced this specific behavior, especially when using dynamic QML window creation/destruction? Do you know of any workarounds or configuration settings that might mitigate this leak?

    Thank you for your time and expertise!

    JKSHJ 1 Reply Last reply
    0
    • J jason1122

      Hello everyone,

      I am encountering a significant memory leak when repeatedly creating and destroying Window components (using QML) in a Qt 5.15.19 application on Windows. The issue appears to be related to unreleased shared resources. I would greatly appreciate any help or insight you can provide.


      Environment for Reproduction

      • OS: Windows 10 (running in a VMware virtual machine)
      • Qt Version: 5.15.19
      • Application Type: Qt Quick (QML)
      • Compiler/Architecture: The test program is compiled as a 32-bit application. (MSVC 2022, 32-bit)

      Minimal Reproducible Test Code

      The issue can be observed by running the following two QML files. The Timer in main.qml continuously creates and destroys a new SessionWin instance every second.

      main.qml

      import QtQuick 2.12
      import QtQuick.Window 2.12
      import QtQuick.Controls 2.12
      
      Window {
          id: id_main_win
          visible: true
          width: 1280
          height: 720
          color: "blue"
      
          property int createCount: 0
      
          Text {
              anchors.centerIn: parent
              text: createCount
              font.pixelSize: 30
          }
      
          Button {
              id: top_right_button
              width: 200
              height: 40
              font.pixelSize: 16
              text: "stop"
      
              anchors {
                  top: parent.top
                  right: parent.right
              }
      
              onClicked: {
                  console.info(`stop createSession timer, createCount ${createCount}`)
                  id_timer.stop()
                  if (id_timer.tmpwin) {
                      id_timer.tmpwin.destroy()
                      id_timer.tmpwin = null
                  }
              }
              background: Rectangle {
                  color: top_right_button.hovered ? "#e0e0e0" : "red"
                  radius: 5
              }
          }
      
          Button {
              id: top_left_button
              width: 200
              height: 40
              font.pixelSize: 16
              text: "restart"
      
              anchors {
                  top: parent.top
                  left: parent.left
              }
      
              onClicked: {
                  console.info("restart createSession timer")
                  id_timer.restart()
      
              }
              background: Rectangle {
                  color: top_left_button.hovered ? "#e0e0e0" : "red"
                  radius: 5
              }
          }
      
          Timer {
              id: id_timer
              repeat: true
              interval: 1000 // Creates and destroys a window every second
              property var tmpwin: null
              onTriggered: {
                  if (tmpwin) {
                      tmpwin.destroy()
                      tmpwin = null
                  }
      
                  tmpwin = createSession()
              }
          }
      
          Component {
              id: id_sess
              SessionWin {
              }
          }
      
          function createSession() {
              var win = id_sess.createObject(id_main_win)
              createCount += 1
              return win
          }
      }
      

      SessionWin.qml

      import QtQuick 2.12
      import QtQuick.Window 2.12
      import QtQuick.Controls 2.12
      
      Window {
          id: id_session_win
          width: 1024
          height: 1024
          visible: true
      
          Component.onCompleted: {
              console.debug(`memoryTracer: create object: ${this}, size: ${width}x${height}`)
          }
      
          Component.onDestruction: {
              console.debug(`memoryTracer: destroy object: ${this}`)
          }
      }
      

      Preliminary Analysis Findings

      1. Shared Memory Accumulation: The process's shared memory usage continuously increases over time.
        • Using the vmmap.exe tool to examine the process's virtual address space, I found that each creation/destruction cycle leaves behind a shared memory block of approximately 4320 KB.
        • For instance, if I repeat the create/destroy cycle 80 times, there will be 80 unreleased shared memory blocks of 4320 KB each.
      2. Shared GPU Resource: When the test program is run on a physical machine (instead of a VM), the leaked memory region is identified as being related to Shared GPU resources. This suggests an unreleased graphics/window resource.

      I suspect this may be a bug related to how Qt 5.15.19 handles the cleanup of platform-specific resources (possibly related to the windowing system or graphics backend) when a QML Window is dynamically destroyed.

      Has anyone else experienced this specific behavior, especially when using dynamic QML window creation/destruction? Do you know of any workarounds or configuration settings that might mitigate this leak?

      Thank you for your time and expertise!

      JKSHJ Offline
      JKSHJ Offline
      JKSH
      Moderators
      wrote last edited by
      #2

      Hi @jason1122, and welcome!

      Do you still see the memory leak with Qt 6.10.0?

      Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved