我喜欢为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语言的解决方案!
答案 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)
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...
}
由于它会回绕到较低的值,因此您可以轻松检查它是否溢出。