【问题标题】:Why does WSAStringToAddress take a non-const AddressString?为什么 WSAStringToAddress 采用非常量的 AddressString?
【发布时间】: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


【解决方案1】:
  1. Windows 是一个 C API,因此定义为 "Some string" 的 C 字符串不是常量。 C++ 通过使它们保持不变来改变这一点。
  2. 是的,使用const_cast<LPTSTR>("my string"). 抛弃常量是完全安全的

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-21
  • 2018-01-26
  • 1970-01-01
  • 2016-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多