【发布时间】:2017-02-18 13:13:11
【问题描述】:
WSAStringToAddress 的 Windows 文档指出:
INT WSAAPI WSAStringToAddress(
_In_ LPTSTR AddressString,
_In_ INT AddressFamily,
_In_opt_ LPWSAPROTOCOL_INFO lpProtocolInfo,
_Out_ LPSOCKADDR lpAddress,
_Inout_ LPINT lpAddressLength
);
AddressString 是 _In_ 参数,而不是 _Inout_ 参数。我不清楚为什么 API 需要一个非常量指针,并导致编译失败,因为我有一个 const char*。
我的第一个问题是,为什么WSAStringToAddress 采用非常量指针?
我的第二个问题是,抛弃 const-ness 是否安全? WSAStringToAddress 会修改 char* 参数吗?
这里有更多的背景故事......我正在尝试在 inet_addr 替换中使用 WSAStringToAddress,因为在当代版本的 Visual Studio 下不推荐使用警告。
answer provided by Petar Korponaić 的问题中详述了同样的问题。科尔波奈奇也遇到了同样的问题。这是额外副本的原因:
int inet_pton(int af, const char *src, void *dst)
{
struct sockaddr_storage ss;
int size = sizeof(ss);
char src_copy[INET6_ADDRSTRLEN+1];
ZeroMemory(&ss, sizeof(ss));
/* stupid non-const API */
strncpy (src_copy, src, INET6_ADDRSTRLEN+1);
src_copy[INET6_ADDRSTRLEN] = 0;
if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0)
...
}
【问题讨论】:
-
有一些 Windows api - 这可能是也可能不是其中之一 - 修改字符串到位 - 例如添加一个终止零以使用一个字符串片段和一个预期为零的 api终止的字符串,然后恢复被覆盖的字符。如果你只是抛弃了常量,你可以引入竞争条件或如果源字符串是存储在只读内存中的文字,则引发异常。
-
@ChrisBecke:这些参数是使用
_Inout_SAL 注释之一(如CreateProcess 中的lpCommandLine 参数)。但是,在这种情况下,有一个_In_注释。由于 SAL 注释在调用站点和实现都被评估,我假设 AddressString 可以是一个常量。我认为部署的 Ws2_32.dll 二进制文件编译时不会出现警告(或禁用某些 SAL 警告),尽管我没有对代码进行逆向工程。
标签: winapi parameters constants winsock2