9

我喜欢为 VS.NET 和 GCC 提供免费的代码警告,并且我喜欢准备好我的 64 位代码。

今天我写了一个小模块,它处理内存缓冲区并通过文件样式接口提供对数据的访问(例如,您可以读取字节、写入字节、四处寻找等)。

作为当前读取位置和大小的数据类型,我使用了 size_t,因为这似乎是最自然的选择。我绕过警告,它也应该在 64 位下工作。

以防万一:我的结构如下所示:

typedef struct
{
  unsigned char * m_Data;
  size_t          m_CurrentReadPosition;
  size_t          m_DataSize;
} MyMemoryFile;

的符号size_t似乎在实践中没有定义。谷歌代码搜索证明了这一点。

现在我处于两难境地:我想检查是否有size_t溢出,因为我必须处理用户提供的数据,而第三方库将使用我的代码。但是,对于溢出检查,我必须知道符号。它在实施中产生了巨大的差异。

那么 - 我到底应该如何以独立于平台和编译器的方式编写这样的代码?

我可以size_t在运行或编译时检查签名吗?那将解决我的问题。或者,也许size_t一开始就不是最好的主意。

有任何想法吗?

编辑:我正在寻找 C 语言的解决方案!

4

6 回答 6

13

关于size_t 是签名还是未签名以及 GCC(来自旧的 GCC 手册 - 我不确定它是否仍然存在):

size_t2.4 版之前的 GCC 类型和版本存在潜在问题 。ANSI C 要求它 size_t始终是无符号类型。为了与现有系统的头文件兼容,GCC 将size_tin 定义stddef.h为系统定义的任何类型sys/types.h。大多数定义 size_tin 的Unix 系统将其定义sys/types.h为有符号类型。库中的某些代码依赖于size_t无符号类型,如果有符号则无法正常工作。

The GNU C library code which expects size_t to be unsigned is correct. The definition of size_t as a signed type is incorrect. We plan that in version 2.4, GCC will always define size_t as an unsigned type, and the 'fixincludes' script will massage the system's sys/types.h so as not to conflict with this.

In the meantime, we work around this problem by telling GCC explicitly to use an unsigned type for size_t when compiling the GNU C library. 'configure' will automatically detect what type GCC uses for size_t arrange to override it if necessary.

If you want a signed version of size_t use ptrdiff_t or on some systems there is a typedef for ssize_t.

于 2008-10-15T21:31:52.337 回答
5

size_t应该是无符号的。

它通常被定义为无符号长。

我从未见过以其他方式定义它。ssize_t是它的签名对应物。

编辑:GCC 在某些情况下将其定义为已签名。在 ASNI C 模式或 std-99 下编译应该强制它是无符号的。

于 2008-10-15T20:51:15.727 回答
5

size_t根据 C++ C 标准,是无符号整数类型。任何已size_t签名的实现都严重不合格,并且可能还存在其他可移植性问题。它保证在溢出时回绕,这意味着您可以编写类似if (a + b < a)查找溢出的测试。

size_t是任何涉及记忆的优秀类型。你做对了。

于 2008-10-15T21:09:12.990 回答
2

对于 C 语言,请使用IntSafe。也由 Microsoft 发布(不要与 C++ 库 SafeInt 混淆)。IntSafe 是一组 C 语言函数调用,可以安全地执行数学运算和转换。 更新了 intsafe 函数的 URL

于 2008-10-15T21:07:39.233 回答
0

使用安全。它是由 Michael Howard 设计并从 Microsoft 开源发布的一个类。它旨在处理被确定为存在溢出风险的整数。所有溢出都转换为异常并进行处理。该类旨在使正确使用变得容易。

例如 :

char CouldBlowUp(char a, char b, char c)
{
   SafeInt<char> sa(a), sb(b), sc(c);

   try
   {
     return (sa * sb + sc).Value();
   }
   catch(SafeIntException err)
   {
      ComplainLoudly(err.m_code);
   }

   return 0;
}

此外,微软内部在 Office 等产品中也大量使用了 safeint。

参考: 链接文本

于 2008-10-15T20:54:48.090 回答
-1

我不确定我是否完全理解这个问题,但也许你可以这样做:

temp = value_to_be_added_to;

value_to_be_added_to += value_to_add;

if (temp > value_to_be_added_to)
{
  overflow...
}

由于它会返回到较低的值,因此您可以轻松检查它是否溢出。

于 2008-10-15T20:58:11.717 回答