Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# UWP文件操作导致内存泄漏?_C#_Uwp_C++ Winrt - Fatal编程技术网

C# UWP文件操作导致内存泄漏?

C# UWP文件操作导致内存泄漏?,c#,uwp,c++-winrt,C#,Uwp,C++ Winrt,更新:我被可靠地告知微软正在调查此事。这些API调用无法正常工作,因此我尝试使用std::filesystem,但在UWP应用程序中,对于“代理位置”,这不起作用 只需查询文件系统,我就可以得到数百个泄露的MEG考虑到UWP只允许在应用程序处于后台时使用128MB内存*,这似乎有点绝望。我认为这是内存泄漏是对的还是有什么解释?下面显示的代码只是递归地获取c:/program文件的所有StorageFile对象(需要很长时间)。两个月前,我已经尝试向microsoft报告了这一点(最后的链接)

更新:我被可靠地告知微软正在调查此事。这些API调用无法正常工作,因此我尝试使用std::filesystem,但在UWP应用程序中,对于“代理位置”,这不起作用


只需查询文件系统,我就可以得到数百个泄露的MEG考虑到UWP只允许在应用程序处于后台时使用128MB内存*,这似乎有点绝望。我认为这是内存泄漏是对的还是有什么解释?下面显示的代码只是递归地获取c:/program文件的所有StorageFile对象(需要很长时间)。两个月前,我已经尝试向microsoft报告了这一点(最后的链接)

*这个信息似乎是错误的;UWP内存余量显然因设备而异,而在桌面上它似乎实际上是无限的。有一个函数AppMemoryUsageLimit可以查询此信息

c#/winrt和c++/winrt示例如下;您可能必须进入windows设置: 文件系统隐私设置->允许应用程序访问您的文件系统

c#/winrt:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using System.Diagnostics;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace MemoryLeak001_CSharp_2
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {

            GC.Collect();

            Trace.WriteLine("\nButton_Click started...\n");
            {
                Windows.Storage.StorageFolder _root = await Windows.Storage.StorageFolder.GetFolderFromPathAsync("C:\\program files");

                var _storageFiles = await _root.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByName);
                var _count = _storageFiles.Count;
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();
            Trace.WriteLine("\nButton_Click finished.\n");
        }
    }
}
#include "pch.h"
#include <thread>
#include <winrt/Windows.Storage.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Storage.Search.h>

using namespace winrt;
using namespace Windows::Foundation;
using namespace winrt::Windows::Storage::Streams;
using namespace winrt::Windows::Storage::Search;



int main()
{
    init_apartment();

    __int64 _count{ -1 };

    {
        winrt::Windows::Storage::StorageFolder _root = winrt::Windows::Storage::StorageFolder::GetFolderFromPathAsync(L"c:\\program files\\").get();
        auto _storageFiles = _root.GetFilesAsync(CommonFileQuery::OrderByName).get();
        _count = _storageFiles.Size();
        printf("Count: %d", _count);
    }

    // The file-open stuff has gone out of scope now.       
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用System.Runtime.InteropServices.WindowsRuntime;
使用Windows基金会;
使用Windows。
使用Windows.UI.Xaml;
使用Windows.UI.Xaml.Controls;
使用Windows.UI.Xaml.Controls.Primitives;
使用Windows.UI.Xaml.Data;
使用Windows.UI.Xaml.Input;
使用Windows.UI.Xaml.Media;
使用Windows.UI.Xaml.Navigation;
使用系统诊断;
//空白页项模板被记录在https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
命名空间MemoryLeak001_CSharp_2
{
/// 
///可以单独使用或在框架内导航到的空页。
/// 
公共密封部分类主页面:第页
{
公共主页()
{
this.InitializeComponent();
}
专用异步无效按钮\u单击(对象发送方,路由目标)
{
GC.Collect();
Trace.WriteLine(“\n按钮\u单击开始…\n”);
{
Windows.Storage.StorageFolder\u root=等待Windows.Storage.StorageFolder.GetFolderFromPathAsync(“C:\\program files”);
var\u storageFiles=await\u root.getfileasync(Windows.Storage.Search.CommonFileQuery.OrderByName);
var\u count=\u storageFiles.count;
}
GC.Collect();
GC.WaitForPendingFinalizers();
Trace.WriteLine(“\n按钮\u单击完成。\n”);
}
}
}
c++/winrt:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using System.Diagnostics;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace MemoryLeak001_CSharp_2
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {

            GC.Collect();

            Trace.WriteLine("\nButton_Click started...\n");
            {
                Windows.Storage.StorageFolder _root = await Windows.Storage.StorageFolder.GetFolderFromPathAsync("C:\\program files");

                var _storageFiles = await _root.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByName);
                var _count = _storageFiles.Count;
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();
            Trace.WriteLine("\nButton_Click finished.\n");
        }
    }
}
#include "pch.h"
#include <thread>
#include <winrt/Windows.Storage.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Storage.Search.h>

using namespace winrt;
using namespace Windows::Foundation;
using namespace winrt::Windows::Storage::Streams;
using namespace winrt::Windows::Storage::Search;



int main()
{
    init_apartment();

    __int64 _count{ -1 };

    {
        winrt::Windows::Storage::StorageFolder _root = winrt::Windows::Storage::StorageFolder::GetFolderFromPathAsync(L"c:\\program files\\").get();
        auto _storageFiles = _root.GetFilesAsync(CommonFileQuery::OrderByName).get();
        _count = _storageFiles.Size();
        printf("Count: %d", _count);
    }

    // The file-open stuff has gone out of scope now.       
}
#包括“pch.h”
#包括
#包括
#包括
#包括
#包括
使用名称空间winrt;
使用名称空间Windows::Foundation;
使用名称空间winrt::Windows::Storage::Streams;
使用名称空间winrt::Windows::Storage::Search;
int main()
{
init_公寓();
__int64_计数{-1};
{
winrt::Windows::Storage::StorageFolder _root=winrt::Windows::Storage::StorageFolder::GetFolderFromPathAsync(L“c:\\program files\\”).get();
auto _storageFiles=\u root.getFileAsync(CommonFileQuery::OrderByName).get();
_计数=_storageFiles.Size();
printf(“计数:%d”,\u计数);
}
//文件打开的内容现在已超出范围。
}

更多:重复执行c++/winrt: 更新:c++/winrt版本使用的内存是c#版本的10倍(峰值使用)。我将向c++/winrt人员询问这方面的问题。

更新:我已经成功地制作了一个C版本,其中的内存似乎被回收,因此内存使用量只是一个峰值,而不是一个步骤: 请再次注意,要使此应用正常工作,我必须在windows中进行文件系统隐私设置:
这似乎是C++/WinRT版本使用的内存是C版本的10倍的预期行为

<>关于C++中内存使用增加,与C++相比,.NET可以缓存C++对象,因为它们是更昂贵的对象,可以用来创建和删除。这可能意味着,一旦对象被取消引用,它可能仍然被保存在内存中,因为GC还没有机会运行,一旦它这样做,它将运行CoFreeUnusedLibrariesEx()调用,然后继续调用DllCanLoadNow()

当应用程序运行时,C++COM对象可能会占用更多内存,但是一旦GC运行或应用程序中的条件需要清理时,分配的资源最终将被释放。(基于当前内存使用情况、可用内存、性能和其他因素。)


垃圾收集器最终将基于各种因素运行,包括应用程序性能和剩余的总可用内存。如果应用程序一直运行到崩溃并出现OutOfMemory异常,那么这可能表明存在泄漏,因为资源没有按照垃圾收集器的预期释放,也没有更多的资源能够分配到内存中。

如果应用程序一直运行到内存耗尽并崩溃,这就是泄漏。如果它运行到某个非破坏点并停止,则可能只是延迟了垃圾收集。你是从中得到了实际的问题,还是仅仅注意到了内存的使用?我认为它最终会崩溃。在c#中,托管内存保持较低,而本机内存变高。在c++/winrt中,没有垃圾收集,但内存消耗也非常高。缓存实现显示出与真正的资源泄漏相同的资源消耗模式。您需要确保系统最终会耗尽内存,以区分这些。还要注意C++实现垃圾收集,它只是确定性的。特别是COM,它与.NET的CLR实现非常接近。有见地的阅读:.COM是引用,正如您所知。至少当所有的东西超出范围时,C++版本都应该释放内存,对吧?我会认为如果COM使用1g