在size_t添加中溢出

时间:2008-10-15 20:48:15

标签: c integer-overflow size-t

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

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

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

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

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

size_t的签名似乎没有在实践中定义。 Google代码搜索证明了这一点。

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

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

我可以在运行或编译时检查size_t的签名吗?这将解决我的问题。或者也许size_t首先不是最好的主意。

有什么想法吗?

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

6 个答案:

答案 0 :(得分:12)

关于size _ t是签名还是未签名和GCC(来自旧的GCC手册 - 我不确定它是否仍在那里):

  

有一个潜在的问题   size_t GCC之前的类型和版本   发布2.4。 ANSI C要求   size_t始终是无符号类型。对于   与现有系统兼容   头文件,GCC定义了size_t   stddef.h是什么类型的   系统sys/types.h将其定义为   是。大多数定义的Unix系统   size_t中的sys/types.h,将其定义为   是签名类型。一些代码在   库取决于size_t是一个   无符号类型,不起作用   正确的,如果它已签名。

     

期望的GNU C库代码   size_t未签名是正确的。该   将size_t定义为签名类型   是不正确的。我们计划在版本中   2.4,GCC将始终将size_t定义为无符号类型,并且   'fixincludes'脚本将按摩   系统的sys/types.h以免   与此发生冲突。

     

与此同时,我们努力解决这个问题   通过告诉GCC明确的问题   在size_t时使用无符号类型   编译GNU C库。   'configure'会自动检测   GCC用于size_t安排的类型   如有必要,可以覆盖它。

如果您希望size_t的签名版本使用ptrdiff_t,或者在某些系统上有ssize_t的typedef。

答案 1 :(得分:4)

size_t应该是未签名的。

通常定义为无符号长。

我从未见过如此定义。 ssize_t是其签署的对手。

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

答案 2 :(得分:4)

根据C ++ C标准,

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

size_t对于涉及内存的任何内容都是一个很好的类型。你做对了。

答案 3 :(得分:2)

对于C语言,请使用IntSafe。也是由微软发布的(不要与C ++库SafeInt混淆)。 IntSafe是一组C语言函数调用,可以执行数学运算并安全地进行转换。 updated URL for intsafe functions

答案 4 :(得分:0)

使用safeint。这是由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。

价: link text

答案 5 :(得分:-1)

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

temp = value_to_be_added_to;

value_to_be_added_to += value_to_add;

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

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