AppKit+0x000000000081e640(arm64 7038,×56,new_class #1)EXC_BREAKPOINT,CrBrowserMain(主线程)utility_tool/DVDFabStream/Stream/DownloadUi/TaskQueueManager.cpp:21881. dump 内嵌异常消息(3/3 个抽检 dump 一致):
`*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '*** -[NSURL initFileURLWithPath:]: nil string parameter'`
2. 本机 macOS 26.5.1 的 AppKit build(2685.60.104)与 dump 完全一致,用 lldb
对 shared cache 符号化关键帧:
AppKit+0x81e640 = +[NSApplication _crashOnException:]AppKit+0x306220 = -[NSApplication reportException:]AppKit+0x309b38 = -[NSSound initWithContentsOfFile:byReference:]Foundation+0x35860/0x354cc = -[NSURL initFileURLWithPath:] / +[NSURL fileURLWithPath:]3. 栈:QObject::event(QTimerEvent,qobject.cpp:1369)→ app 帧 → NSSound init
→ NSURL fileURLWithPath: nil → 抛异常 → 未捕获 → _crashOnException 主动断点。
与 TaskQueueManager.cpp:1587/1931 的
QTimer::singleShot(0, this, [this,…]{ playSound(…); }) 吻合。
4. 反汇编 appdepends/lib/common/mac/Release/libutilosm_u.a 中
sndPlaySound(const char*, uint)(MacAPIUse.o):
path == NULL 时直接返回(cbz x20)→ stopPlaySound 的 NULL 调用是安全的;[NSString stringWithUTF8String:path] → [[NSSound alloc] initWithContentsOfFile:… byReference:YES],无 nil 检查。
TaskQueueManager::playSoundFile(TaskQueueManager.cpp:2185-2206)mac 分支:
QByteArray ba = filePath.toLatin1(); // ← line 2188,mac 上错误的编码
lpszFile = ba.data();
...
sndPlaySound(lpszFile, bLoop); // mac 实现按 UTF-8 解码
音频路径含 Latin-1 高位字符(é、ü、ñ 等,欧洲用户名/安装路径常见)时,
toLatin1() 输出 0x80-0xFF 单字节,不是合法 UTF-8,
stringWithUTF8String: 返回 nil → initWithContentsOfFile:nil →
+[NSURL fileURLWithPath:nil] 抛 NSException。Qt 事件循环内无 ObjC 捕获 → 必崩。
放大因素:下载完成提示音默认开启(GetSoundDownloadFinishState() 默认 true,
appconfig.cpp:1196-1206),默认音频路径 = g_GetResourcesDir() + "/succ.wav"
随安装路径继承非 ASCII 字符 → 命中用户每次下载完成必崩。
utility_tool @ dev_vs2019,TaskQueueManager::playSoundFile:
1. mac 分支改用 filePath.toUtf8()(sndPlaySound 底层按 UTF-8 解码);
2. 与 Windows 分支对齐,增加空串/文件存在检查后再调用。
单函数局部修改,不影响 Windows 路径(#ifdef OS_WIN 分支不动)。
见 daily summary 的 deferred 项,机制不同,另行分析。