РЕДАКТИРОВАТЬ: изменение 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)
Я предположил, что проблемы начинают возникать, когда вышеприведенное вычисление устанавливается на 32-й бит entrySize * startIndex
. Однако, это все еще работало, когда я использовал первое значение startIndex
, у которого был включен 32-й бит. Также отображается
Мои вопросы:
- является результатом
int
*unsigned int
, считающимся подписанным или
без знака? какой ранг типа результата? умножение может
вероятно, переполнение до 8-байтовых типов, и я предполагаю, что компилятор предотвращает
потерять точность, верно?
startAddr
- это void*
. затем добавляется
на любое значение и тип, рассчитанный в первом вопросе. это void*
считается signed
или unsigned
? моя догадка, конечно, unsigned
value
, но я не могу ее подтвердить.
- Какие целочисленные промоушены происходят в startAddr + << <strong>result >>.
- Может ли наше заявление while никогда не останавливаться (на практике)? Если правая часть неравенства представляет собой число со знаком (шириной не менее 8 байтов), то будет ли левая сторона (curr_addr) повышаться как число со знаком, что приведет к бесконечному циклу?
- Пошаговое объяснение будет приветствоваться:)
Я прочитал все, что содержится в этих ссылках, и все еще не знал:
- https://www.oreilly.com/library/view/c-in-a/0596006977/ch04.html
- Целочисленное преобразование ранга со знаком и без знака в int