不直接使用字符串时CreateProcess@Unhandled异常

Posted

技术标签:

【中文标题】不直接使用字符串时CreateProcess@Unhandled异常【英文标题】:CreateProcess @ Unhandled exception when not using directly a string 【发布时间】:2013-04-02 21:35:29 【问题描述】:

我正在尝试使用 CreateProcess 打开游戏 .exe,但我遇到了未处理的异常错误。我已经弄清楚了问题和解决方案,但是我需要从文件对话框中获取 CreateProcess 的第二个参数的路径(该部分已完成并且可以工作)。问题是:

对于 CreateProcess 的第二个参数,我需要声明一个带有它的值的变量(第二个参数),但是如果我“指向”它指向在文件对话框中选择的文件的路径的变量,它不再起作用了。

如果这是一个非常愚蠢的问题,我很抱歉,但我是从 C++ 开始的。

有效的代码在这里:

    wchar_t szGameDir[] = L"PATH_TO_EXE";

    if ( CreateProcess (
        NULL,
        szGameDir, NULL, NULL, FALSE,
        CREATE_UNICODE_ENVIRONMENT,
        NULL, NULL,
        &pstStartupInfo, &pstProcInfo ) )

但是当我将 szGameDir 设置为 'pszGameDir' 的值(用户选择的 EXE 的路径)时,它给出了未处理的异常错误...

wchar_t* szGameDir = pszGameDir;

if ( CreateProcess (
        NULL,
        szGameDir, NULL, NULL, FALSE,
        CREATE_UNICODE_ENVIRONMENT,
        NULL, NULL,
        &pstStartupInfo, &pstProcInfo ) )

这是我初始化“pszGameDir”的地方:

OPENFILENAME DialogBox;
ZeroMemory ( &DialogBox, sizeof(DialogBox) );

DialogBox.lStructSize       = sizeof(OPENFILENAME);
DialogBox.hwndOwner         = NULL;
DialogBox.lpstrFilter       = L"Grand Theft Auto: Vice City (*.exe)\0*.exe\0";
DialogBox.lpstrFile         = (LPTSTR)this->pszGameDir;
DialogBox.nMaxFile          = MAX_PATH;
DialogBox.nMaxFileTitle     = sizeof ( L"gta-vc.exe" );
DialogBox.lpstrTitle        = L"Please, select 'gta-vc.exe'";
DialogBox.Flags             = 0x02000000 | 0x00001000 | 0x00000400 | 0x10000000 | 0x00020000 | 0x00000800 | 0x0000008;
DialogBox.nFileExtension    = (WORD)"exe";
DialogBox.lpstrDefExt       = L"exe";

return GetOpenFileName ( &DialogBox ) != 0 ? 1 : NULL;

有人可以帮助我吗? (是的,我已经搜索过了,但老实说我还没有找到这个具体的东西,我也无法修复它..)

【问题讨论】:

您能告诉我们您是如何声明pszGameDir 的,以及您将它指向szGameDir 的位置吗?我怀疑,您是在声明它但没有对其进行初始化..然后初始化其中一个..使另一个无效。 除了@SimonWhitehead 所说的之外,请不要将NULL 指定为CreateProcess 的第一个参数,因为这会在系统尝试推断要使用的路径时导致奇怪的问题,并且是强制修改第二个参数指向的字符串。而是做对,并将可执行文件的路径作为第一个参数传递。阅读更多MSDN 我在一个类中声明 'pszGameDir' 作为公共成员(这只是一个测试项目,我会重写所有内容,所以我并不担心变量是公共的还是私有的) : "LPTSTR pszGameDir;" - 然后我在“GetVCPath”函数中初始化“pszGameDir”,该函数创建一个文件对话框并使用“GetOpenFileName”将正确的路径设置为“pszGameDir”。 'pszGameDir' 持有正确的值,我用 MessageBox 输出了它的值。另外,我不是将 pszGameDir 指向 szGameDir,它是相反的(或者你是这样说的?):( wchar_t* szGameDir = pszGameDir; )。 我很确定这里的问题出在声明中,但我找不到正确的方法.. 请使用适当的代码更新您的问题。代码>单词:) 【参考方案1】:

CreateProcess 需要命令行参数是可写的。阅读MSDN的参数描述:

此函数的 Unicode 版本 CreateProcessW 可以修改此字符串的内容。因此,此参数不能是指向只读内存的指针(例如 const 变量或文字字符串)。如果此参数是一个常量字符串,该函数可能会导致访问冲突。

恐怕它必须是可写的。

【讨论】:

我很久以前就知道了,我只是没有意识到我该怎么做。对不起,但我是 C++ 的新手。。 @xxx 您需要将字符串复制到可写缓冲区中。使用内置 C strcpy 函数或 lstrcpy(Win32 API 的一部分)之类的东西。 好的,我已经阅读了这里的所有消息,回家后我会更改这里提到的内容,我会继续努力解决我的问题。 我一直在尝试,但我无法解决问题.. AFAIK,LPTSTR 是一个非常量 TCHAR(它也不是指针,对吧?)所以我看不到为什么我仍然会出现内存冲突。这是我尝试过的:LPTSTR szGameDir = 0; if ( SUCCEEDED(StringCchCopy( szGameDir, MAX_PATH, pszGameDir )) ) MessageBoxW ( NULL, szGameDir, L"Msg", NULL ); pszGameDir 现在也是 LPTSTR(如果不是指针,我忘了删除 'p' 前缀)。

以上是关于不直接使用字符串时CreateProcess@Unhandled异常的主要内容,如果未能解决你的问题,请参考以下文章

Java 输出字符串对象时先转换成基本数据再转换成字符串,才输出,为啥不直接输出字符串对象呢

Equalizing Two Strings

警告:不推荐使用“字符”:请直接使用字符串或子字符串

为什么Redis不直接使用C语言的字符串?看完直接吊打面试官!

在不直接触发选择事件的情况下动态获取组合框 displayField 和 valueField 值

PHP输出json数据时,中文不进行unicode编码