2

我正在将应用程序从 32 位移植到 64 位。该应用程序包括 gSoap 生成的 ANSI C 源代码。几个生成的soap函数的原型包括int参数列表中的数据类型,例如:

int PASCAL FAR setsockopt (
                       __in SOCKET s,
                       __in int level,
                       __in int optname,
                       __in_bcount_opt(optlen) const char FAR * optval,
                       __in int optlen);

但是,当在 stdsoap2.c 中调用时,此示例中的第 5 个参数将传递给sizeof宏:

if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
{ ...
}

sizeof宏返回一个类型的值,它size_t只是一个unsigned int. 在 32 位环境下编译时,这没有问题,但是在 64 位环境下编译时,警告: “从 unsigned __int64 to转换 int 可能会丢失数据”

我了解数据丢失问题。我的问题是它应该在哪里以及如何放置在代码中,以解决作为内部传递(int)的每个宏的类型转换不足的问题(单独有 32 个警告)。如果可能,我想避免编辑自动生成的源文件。sizeofintstdsoap2.cstdsoap.c

对于那些熟悉gsoap方法的人,我包括以下内容:

#ifdef WITH_SOAPDEFS_H
# include "soapdefs.h"      /* include user-defined stuff */
#endif

soapdefs.h在我的项目中使用。这个文件的项目范围很广,也许这个文件是解决问题的好地方,那么问题就是如何

4

2 回答 2

4

size_t不是“只是一个unsigned int”;正如警告所示,在 64 位平台上,它通常比这大。

您应该在哪里进行检查取决于应用程序,但如果您要传递sizeof表达式的值,则可以将其替换为适当定义的常量:

enum {
    SIZEOF_LINGER = sizeof(struct linger);
};

如果常量太大而无法转换,编译器会发出警告,所以如果你用 (相当于 GCC's) 编译-Wall -Werror,你是安全的。

于 2011-07-06T15:47:14.480 回答
1

如果我无法将采用 int 的方法更改为采用 size_t,我通常会决定在 C++ 中使用 boost::numeric_cast 或在 C 中使用类似的方法,这似乎是最好的做法,并且在仍然保持安全的同时有效地消除了警告.

基本思想是:

int safe_cast( size_t n )
{
  if( n > INT_MAX )
  {
     //do something to handle this error
  }
  return (int) n;
}

但是,在您的情况下,您可以确定它sizeof( struct linger )不会超过 INT_MAX,因此您不妨提供一个全局常量,它是一个 int 并保持该大小。

于 2011-07-06T15:49:42.120 回答