You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 9混合程序中同时初始化tbbmalloc_proxy与保证AppDomain.BaseDirectory有效的实现方案咨询

.NET 9混合程序中同时初始化tbbmalloc_proxy与保证AppDomain.BaseDirectory有效的实现方案咨询

我目前正在把一个混合代码库从.NET Framework 4.7.2迁移到.NET 9。在4.7.2中,我们用C++/CLI EXE作为程序入口,这样可以很方便地在主文件中引入tbbmalloc_proxy.h初始化TBB内存分配器,之后再调用C#代码。但.NET 9不再支持C++/CLI EXE,所以我只能选择原生C++ EXE或者C# EXE作为入口,不过两种方案各有问题,想请教大家有没有解决办法。


方案一:原生C++ EXE作为入口,通过C++/CLI DLL启动WPF App

这个方案能成功初始化tbbmalloc_proxy,但System.AppDomain.CurrentDomain.BaseDirectory为空,导致WPF的MediaElement组件报错。

代码实现

原生C++ EXE(Main.cpp)

#include "Launcher/Launcher.h"
#include <objbase.h>
#include <tbb/tbbmalloc_proxy.h>

int WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    PSTR lpCmdLine,
    int nCmdShow
) {
    // 对应托管代码中的[System::STAThreadAttribute]
    HRESULT lResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    if (FAILED(lResult)) {
        return -1;
    }

    Launch();
    return 0;
}

C++/CLI DLL(Launcher.h)

#pragma once

#if defined( LAUNCHER_BUILD )
#define LAUNCHER_DLL __declspec(dllexport)
#else
#define LAUNCHER_DLL __declspec(dllimport)
#endif

LAUNCHER_DLL void Launch();

C++/CLI DLL(Launcher.cpp)

#include "Launcher.h"
#include <tbb/tbbmalloc_proxy.h>

void LogTbbMalloc() {
    char** func_replacement_log;
    int func_replacement_status = TBB_malloc_replacement_log(&func_replacement_log);
    if (func_replacement_status != 0) {
        System::Diagnostics::Debug::WriteLine("tbbmalloc replace failed!");
    }
    System::Diagnostics::Debug::WriteLine("tbbmalloc status:");
    for (char** log_string = func_replacement_log; *log_string != 0; log_string++) {
        System::Diagnostics::Debug::WriteLine(gcnew System::String(*log_string));
    }
}

LAUNCHER_DLL void Launch() {
    LogTbbMalloc();
    // LauncherCore.App是C# DLL中的类,继承自System.Windows.Application
    LauncherCore::App^ lpApp = gcnew LauncherCore::App();
    lpApp->InitializeComponent();
    lpApp->Run();
}

方案一的结果

tbbmalloc_proxy初始化成功,日志输出正常:

tbbmalloc status:
Success: free (ucrtbase.dll), byte pattern: <C7442410000000008B4424>
Success: _msize (ucrtbase.dll), byte pattern: <E9ABFFFFFFCCCCCCCCCCCC>
Success: _aligned_free (ucrtbase.dll), byte pattern: <4883EC284885C9740D4883>
Success: _aligned_msize (ucrtbase.dll), byte pattern: <48895C2408574883EC2049>
Success: _o_free (ucrtbase.dll), byte pattern: <488BD1488D0DD604FBFFE9>
Success: _free_base (ucrtbase.dll), byte pattern: <4883EC284885C974164C8B>

但System.AppDomain.CurrentDomain.BaseDirectory为空,WPF的MediaElement在调用System.Windows.Media.MediaPlayerState.OpenMedia(Uri)时,会用这个空路径创建Uri,最终抛出UriFormatException,错误信息是Invalid URI: The URI is empty.。


方案二:C# EXE作为入口,通过C++/CLI DLL启动WPF App

这个方案中System.AppDomain.CurrentDomain.BaseDirectory能正常设置,不会触发MediaElement的错误,但tbbmalloc_proxy初始化失败,性能受到影响。

代码实现

C# EXE(Main.cs)

using System;

internal class Main
{
    [STAThread]
    internal static void Main()
    {
        Launcher.Launch();
    }
}

C++/CLI DLL(Launcher.h)

#pragma once

public ref class Launcher
{
public:
    static void Launch();
};

C++/CLI DLL(Launcher.cpp)

#include "Launcher.h"
#include <tbb/tbbmalloc_proxy.h>

void LogTbbMalloc() {
    char** func_replacement_log;
    int func_replacement_status = TBB_malloc_replacement_log(&func_replacement_log);
    if (func_replacement_status != 0) {
        System::Diagnostics::Debug::WriteLine("tbbmalloc replace failed!");
    }
    System::Diagnostics::Debug::WriteLine("tbbmalloc status:");
    for (char** log_string = func_replacement_log; *log_string != 0; log_string++) {
        System::Diagnostics::Debug::WriteLine(gcnew System::String(*log_string));
    }
}

void Launcher::Launch() {
    LogTbbMalloc();
    // LauncherCore.App是C# DLL中的类,继承自System.Windows.Application
    LauncherCore::App^ lpApp = gcnew LauncherCore::App();
    lpApp->InitializeComponent();
    lpApp->Run();
}

方案二的结果

System.AppDomain.CurrentDomain.BaseDirectory正常,但tbbmalloc_proxy初始化失败,日志输出:

tbbmalloc replace failed!
tbbmalloc status:

补充背景

值得一提的是,在.NET Framework 4.7.2中,用原生C++ EXE作为入口的方案是完全正常的,BaseDirectory能正确设置,所以我怀疑这是.NET Framework和.NET 9(Core系列)之间的运行时差异导致的。

我现在的目标是找到一个可行的方案,既能:

  1. 正确初始化tbbmalloc_proxy,替换标准C++内存分配函数;
  2. 保证System.AppDomain.CurrentDomain.BaseDirectory有有效的路径,避免WPF组件报错。

有没有大佬遇到过类似的问题,或者有什么思路可以解决这个矛盾?


内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 08:49:52