3

我想调用一个外部程序将 BMP 转换为 DDS 文件,但是在几次调用之后它一直崩溃。我都试过了ShellExecuteCreateProcessor。这里的例子ShellExecute

path = "C:\\pictures";
file = "C:\\pictures\\test.bmp";
string cmd = "-f BC1_UNORM -o " + path + " " + file;
char* cmdConvert= new char[cmd.size()];
strcpy(cmdConvert, cmd.c_str());
int buffSize = (int)strlen(cmdConvert) + 1;
LPWSTR cmdL= new wchar_t[buffSize];
MultiByteToWideChar(CP_ACP, 0, cmdConvert, buffSize, cmdL, buffSize);

SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShEecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = _T("C:\\Texconv\\texconv.exe");
ShExecInfo.lpParameters = cmdL;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_HIDE;
ShExecInfo.hInstApp = NULL;

ShellExecuteEx(&ShExecInfo);
WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
CloseHandle(ShExecInfo.hProcess);

delete convertMe;
delete gah;

之后直接崩溃ShellExecuteEx(&ShExecInfo)。必须有一些竞争条件(或类似的东西),因为它在调试器中运行时不会崩溃(我使用的是 VS2012)。

4

1 回答 1

2

您在第 4 行缺少一个终端零:

char* cmdConvert= new char[cmd.size()];

写:

char* cmdConvert= new char[cmd.size()+1];

正如我现在认为的那样,空字符串缓冲区是一个字节长,因为终端零字符。cmd.size() 不包含此终端字符。对于 sring 缓冲区,您必须在字符串长度上增加一个字节。发布版本中的崩溃是在该缓冲区之后覆盖某些内容的结果。在调试模式下,新操作符在分配缓冲区的开头和结尾填充一些字节以支持缓冲区覆盖检测,这就是它在调试中运行的原因。

于 2013-09-06T11:53:44.920 回答