【问题标题】:C - Recoding malloc() how to detect a negative size used in the call? [duplicate]C - 重新编码 malloc() 如何检测调用中使用的负大小? [复制]
【发布时间】:2015-02-13 13:04:06
【问题描述】:

我目前正在重新编码 malloc() 并且需要处理调用者执行缓冲区大小计算导致负值然后传递给 malloc() 的情况?

我知道参数是size_t,所以我是无符号整数吗?

这样,我想检查将传递给我重新编码的malloc() 的大小,但我该怎么做呢?

因为如果我传递一个负参数,它会变成一个随机数,比如18446744073709551613 我刚刚得到。

所以我的问题是:当参数为size_t(无符号整数)时,如何检查参数是否为负,它会直接转换为天文值,不是吗?

【问题讨论】:

  • 不是随机的,-1 永远是max unsigned value for that type
  • 检查 unsigned int 值是否为负是没有意义的
  • "如何检查参数是否为负" - size_t;根据定义和无符号整数类型,因此在您获得它时它已经是非负数。
  • @all 当然,我知道这一点,但是当我尝试malloc(-3) 并在我的malloc(size_t size) 的第一行打印输出时,我得到了 18446744073709551613。这就是我在这里发布的原因。

标签: c memory-management malloc


【解决方案1】:

一般来说,使用带符号的数字类型从另一个值中减去一个值的所有大小计算都是一个好主意,从而允许检查负值。尽管malloc() 的原型调用了一个无符号值的 size_t,但您可以传递一个有符号值,编译器将为您进行非常简单的转换。

这是我对任何类型的缓冲区大小计算都遵循的一般规则。如果使用有符号变量进行计算,很容易发现缓冲区大小计算问题。

您在问题中写道“因为如果我传递一个负参数,它将被更改为一个随机数,例如 18446744073709551613 我刚刚得到。”这不是真的。大数是负值的无符号表示。这不是随机的。

另一种选择是对值进行边界检查。例如,您可以检查 size_t 的值是否大于 0x7ffffff,这是最大的 32 位有符号值和非常大的缓冲区大小。在我使用的计算机上,以无符号表示的负值将是一个大于 0x8000000 的数字。

【讨论】:

  • 非常感谢,你给了我所有的答案!我知道负参数将被更改为可能的最大数字。但是后来我问“我如何比较它”?但是当我与0x8000000比较时,你给了我完美的答案,真的,真的谢谢!
【解决方案2】:
void *malloc(size_t size);

如您所见,参数是无符号类型,这意味着您不能传递负值。

无论如何,从整数值到无符号类型的转换被定义为保值模max_value+1。

【讨论】:

  • 是的,我知道,但正如我对其他人所说,我做了malloc(size_t size),如果我喜欢malloc(-2),我会直接在malloc() 的第一行打印f 我知道了那个,但是当我尝试像 malloc(-3) 并打印出传递给 malloc() 的内容时,它是 18446744073709551613
  • @nookonee:-3 模 (SIZE_MAX+1) 是一个很大的数字,是的。你的意思是什么?
  • @nookonee 再说一遍,question 是什么?如果 I 使用 18446744073709551613 作为我的 实际 大小请求而不是 -3 调用您的 malloc 函数怎么办?什么/为什么你关心它是否来自一个你甚至没有看到的有符号到无符号的转换?您只需要关心请求的大小是否可以满足。
  • @nookonee:“真实的”malloc 返回 0,因为请求大到无法支持。不是因为它是由之前的负数引起的。
  • @nookonee 如果您无法完成请求的分配,NULL正是您应该返回的。不要使这比它需要的更复杂。有人要一些记忆,然后给你发了一个号码。如果你能做到,那就去做;否则返回 NULL。
【解决方案3】:

由于它是无符号数据类型,因此该值不能为负数。

您的问题更多,是否/如何区分故意传递的巨大价值和来自环绕的巨大价值。

一般来说,这是不可能的。

【讨论】:

  • 除了当前的 64 位机器外,没有理智的开发人员会故意malloc 1e18 字节(即 10 亿 GB),因为每个人都知道今天不存在这么大的机器。
  • @BasileStarynkevitch:有趣的是,很多(名义上理智的)C++ 用户每天都这样做:当new T[n] 的大小计算溢出时,clang 确保将一个巨大的值传递给分配器.因为这通常代表malloc...
  • @BasileStarynkevitch:如果有人试图 malloc -1e18 字节怎么办?突然之间,这个数字看起来很合理。
  • 我的意思很简单,malloc 应该通过失败拒绝任何太大的分配。不管它是转换为 unsigned 的负值(这是一个错误)还是一个巨大的值(例如,由于输入数据损坏)。
【解决方案4】:

是的,你是对的。
size_t 值始终为正,即使在 malloc 函数的情况下传递负值也是如此。如果您传递负值,则此负值将转换为 size_t 类型的无符号值,这会导致一个大的正整数。

例子:

int *p = (int*)malloc(-5);
相当于:

int*p = malloc(SIZE_MAX - 1); // SIZE_MAX 是 size_t 的最大值..!

【讨论】:

  • 哦,好的,谢谢!因此,如果我想尝试一下,我应该将参数中的大小与可能的最大 size_t 进行比较?我对吗 ?但我试过了,我不可能把我的参数和它比较。但是 gcc 说: src/malloc.c:21:15: error: integer constant is so large that it is unsigned [-Werror] if (size >= 18446744073709551613) ^ src/malloc.c:21:3: error: this如果 (size >= 18446744073709551613) ^ 我做错了什么,十进制常量仅在 ISO C90 [-Werror] 中是无符号的?
  • 对不起,但自从 malloc() 接受 2 个参数之后? :-)
  • malloc() 没有两个参数。你的答案看起来和这个很相似:stackoverflow.com/a/17925794/1187415.
  • @Martin:是的,马丁。我已经在问题的评论中提到过 - 可能重复。请检查..!
  • @ShivarajBhat:如果您引用现有答案,那么您应该始终包含指向原始答案的链接。 – 顺便说一句,这个例子(-5)现在是错误的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-23
  • 2012-02-03
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多