C新手:为什么swprintf失败了?

时间:2015-08-22 15:24:33

标签: c winapi

请帮忙!我对C一无所知,但我必须对C代码做一点补充。

我从GetLastError获取错误号(int)并将其显示给表单。相反,我需要获取实际的错误字符串。

我添加了对FormatMessage的调用。调用本身工作正常,但字符串不打印(崩溃程序)。我做错了什么?

wchar_t *textbuf;

if(textbuf==NULL)
        {
            textbuf=(wchar_t *)malloc(4096);
            memset(textbuf,0,4096);
        }

wchar_t *lpMsgBuf;
            FormatMessage(
                FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL, rc, // rc is an int, returned from another function, the result of GetLastError()
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                (LPWSTR)lpMsgBuf, 0, NULL);
swprintf(textbuf, L"%s%s%s\n", textbuf, L"\t\t\t", lpMsgBuf);

3 个答案:

答案 0 :(得分:4)

您没有为\TestAspectJ\bin>java -javaagent:D:\Project\workspaces\RCS_3.2.1\TestAspectJ\src\aspectjweaver-1.6.10.jar oata.Test 分配任何内存。因此,请考虑使用aribtrary大小值,例如textbuf或动态内存分配wchar_t textbuf[50]

此外,在最后一行中,您使用malloc作为第三个参数。这没有任何意义,因为它是空的(或有垃圾)并且总是 可能克服缓冲区大小。

答案 1 :(得分:2)

使用FORMAT_MESSAGE_ALLOCATE_BUFFER标志调用FormatMessage时, lpBuffer 参数必须是指向指针的指针:

wchar_t *lpMsgBuf = NULL;
FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
                FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL,
                rc, // rc is an int, returned from another function, the result of
                    // GetLastError()
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                (LPWSTR)&lpMsgBuf, 0, NULL);

// Do something with lpMsgBuf

// Cleanup system allocated memory
LocalFree( lpMsgBuf );
// Since LocalFree is missing from the Windows 10 SDK you'll need to call HeapFree
// on Windows 10 and above:
HeapFree( GetProcessHeap(), lpMsgBuf );

您仍然需要解决另一个错误。将缓冲区既作为输入又作为输出传递给swprintf是非法的:

  

如果在重叠的字符串之间发生复制,则行为未定义。

答案 2 :(得分:2)

问题是您没有正确地将lpMsgBuf传递给FormatMessage(),并且您对textbuf缓冲区管理不善。

FormatMessage() documentation说:

  

FORMAT_MESSAGE_ALLOCATE_BUFFER
  0x00000100

     

该函数分配一个足够大的缓冲区来保存格式化的消息,并在lpBuffer指定的地址处放置指向分配的缓冲区的指针。 lpBuffer参数是指向LPTSTR的指针;您必须将指针强制转换为LPTSTR(例如,(LPTSTR)&lpBuffer)。 nSize参数指定为输出消息缓冲区分配的最小TCHAR数。当不再需要缓冲区时,调用者应使用LocalFree函数释放缓冲区。

由于您没有将lpMsgBuf初始化为NULL,并且未将 lpMsgBuf地址传递给FormatMessage(),因此它可以将分配的内存地址分配给{ {1}},您最终将垃圾记忆地址作为最终输入参数传递给lpMsgBuf

对于swprintf(),您没有将其初始化为NULL,因此您最终会跳过对textbuf的调用,因此您将垃圾地址传递给malloc()以获取其输出缓冲区和它的第一个输入参数。其中,无论如何都不能使用相同的缓冲区进行输入和输出,这是未定义的行为。

请改为尝试:

swprintf()