【发布时间】:2019-07-30 13:24:37
【问题描述】:
编辑:将 void * 修改为 uint8_t * 值。问题依然存在。
编辑:问题是一个简单的变量溢出,与整数提升无关。
我解决了那段简化代码中的一个错误。类型与源代码中的相同。
unsigned int entrySize; // entrySize is 288
int startIndex, endIndex; // both are 24536838
uint8_t *pStartAddr; // valid initialized pointer (0x34f1e40)
/*Mystery begins...*/
uint8_t *curr_addr = pStartAddr + entrySize * startIndex;
while (curr_addr <= startAddr + entrySize * endIndex)
{
externFunc(curr_addr);
curr_addr+=entrySize;
}
快速浏览此代码似乎很明显,不包括奇怪的类型选择。
然而,在我们的一次崩溃中,curr_addr 似乎获得了一个无效指针。
我的预感是 entrySize * startIndex 存在问题,因为它们的乘法集在第 32 位,并且将 startIndex 和 endIndex 作为有符号类型可能会使编译器混淆要使用的所需值。
在更改了它们的类型后,问题解决了。 但我无法弄清楚究竟是什么出了问题。
我正在使用 64 位机器、x86_64 CPU、gcc (GCC) 4.8.5 20150623 和 linux red hat 发行版(版本 4.8.5-28)
我假设当上面的计算设置在entrySize * startIndex 的第 32 位时问题开始发生。但是,当我使用第一个打开第 32 位的 startIndex 值时,它仍然有效。它也显示了
我的问题是:
- 是
int*unsigned int的值结果被认为是有符号或 未签名?结果类型的等级是多少?乘法可以 可能溢出到 8 字节类型,我假设编译器阻止 失去精度,对吧? -
startAddr是void*。然后添加 到第一个问题中计算的任何值和类型。是void*考虑signed或unsigned?我的预感当然是unsigned value,但我无法支持。 - 什么整数提升发生在 startAddr + result>>。
- 我们的while 语句是否可以永远停止(实际上)?如果不等式的右边是有符号数(宽度至少为 8 字节),那么左边(curr_addr)是否也会被提升为有符号数,导致死循环?
- 欢迎您逐步解释:)
我阅读了这些链接中包含的内容,但仍然一无所知:
【问题讨论】:
-
@IgorGalczak 所有的值都已经定义好了,不用担心 :) startAddr 实际上是来自全局符号的地址(&variableName 来自数据段)
-
如果这段代码是“定义明确的”,你就不会问这么严重的问题,关于“定义明确”的代码到底发生了什么。该代码混合了有符号和无符号整数运算,在溢出时容易出现未定义的行为,并将其与使用
void *指针的计算相结合。 -
@AndrewHenle 我提到的值是流中使用的变量。 startAddr 中设置的指针有效。你是对的,之后发生的事情远没有得到很好的定义。我仍在为我自己寻找一个好的解释,也为将来像我这样的人着想。
-
你不能对空指针使用任何形式的算术。
标签: c types integer-overflow