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

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 212 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 on 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 on 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