编辑:将 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
作为有符号类型可能会使编译器混淆要使用的所需值。
将它们的类型更改为unsinged long 后,问题就解决了。 但我无法弄清楚到底哪里出了问题。
我正在使用 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
的值结果被认为是有符号的或 未签名?结果类型的排名是多少?乘法 jar 可能溢出到 8 字节类型,我假设编译器会阻止 失去精度,对吧? startAddr
是一个void*
。然后添加 到第一个问题中计算的任何值和类型。是void*
被认为是signed
还是unsigned
?我的预感当然是unsigned value
,但我无法支持它。- 在 startAddr + <<result>> 中发生什么整数提升。
- 我们的 while 语句能否永不停止(在实际时间内)?如果不等式右边是一个有符号数(宽度至少8字节),左边(curr_addr)是否也会被提升为有符号数,导致死循环?
- 欢迎逐步解释 :)
我阅读了那些链接中包含的内容,但仍然一无所知:
最佳答案
void*
上的指针运算行为未定义。指针算法只在数组中有效。请注意,您可以设置一个指向数组最后一个元素之后的指针,但不要尝试取消引用它。此规则也适用于出于规则的目的可被视为单个元素数组的对象。
(1) 在你的代码中肯定没有被遵守(你的编译器没有警告你 - 如果没有,将它装箱),(2)可能不是。有点滑稽(就我而言),你的具体问题不相关。
关于c - 理解 C 中的积分运算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55064445/