LINUX.ORG.RU

Почему меняется константная локальная переменная?

 , , ,


0

1

Вот видео https://www.youtube.com/watch?v=c91zzMAaAlo () видео удалено

        const char firstSymbolPosIn7bit = UHDL + 1 + 1;
        // first +1 - for UHDL field
        // other +1 for specify the position of the first letter.

        const char firtSymbolFillers = std::abs(8 - firstSymbolPosIn7bit);

        if (UHDI_present && firtSymbolFillers) {
            unsigned char firstSymbol;
            HexToBin(&payloadText[1], &firstSymbol, 2);
            //↑ this call change const firtSymbolFillers

Есть переменная firtSymbolFillers, локальная, константная, её время жизни видно в видео, как и то что она никак не связана с вызовом ф-ии HexToBin, после которого значение локальной константной переменной меняется.

Есть ли у кого-то догадки из-за чего такое может происходить?

Ну т.е. может ли быть сам исходных код виной такому поведению, или же это какой-то глубинный косяк рантайма от Борланда(Эмбаркадеро)?

И да, все оптимизации в настройках проекта отключены. И это не ошибка в дебагер-прослойке, если запускать не в дебаг режиме, то судя по логам - именно все так и есть, константная переменная меняет своё значение.

Обойти такое, чтобы заставить программу делать то что нужно, можно введя между нужной константой переменной и иф блоком откуда вызывается HexToBin - еще одну переменную затычку - тогда firtSymbolFillers не поменяется. Ну или просто использовать ниже в коде то же выражение, что первично инициировало firtSymbolFillers.

Но блин что за эффект такой? У меня вертится мысли что допустим как-то в коде с индексами массивов (строк) где-то есть ошибка. Но это очень вряд ли, т.к. в ф-ии используются AnsiString - а это vcl строка (Дельфийская, от Си++ к ней только биндинги) - так вот у AnsiString-ов на каждое образение к индексам обязательная проверка валидности индекса, и бросает исключение если что-то не то, так что вряд ли бы я забрел в другой индекс в стеке.. Да и если бы забрел - разве это бы как-то могло повлиять на изменение константной переменной?

★★★★

Портится память где-то? Внутренности функции HexToBin() доступны? Представь их общественности, если да. Полагаю функция должна менять значение неконстантной переменной по адресу? Вылетает за пределы размеров?

Так-то константы они только для компилятора. А дальше будет специфика.

EXL ★★★★★ ()
Последнее исправление: EXL (всего исправлений: 1)
Ответ на: комментарий от EXL

Да вот не знаю портится ли память, если бы это был Linux я бы смог посмотреть в valgrind, а как это делать в C++Builder я не знаю, но программа работает стабильно неделями.

Внутренности доступны

Когда происходит вызов HexToBin(&payloadText[1], &firstSymbol, 2);

Сначала работает cppшный оператор AnsiString (payloadText) -

    char& operator [](const int idx)
    {
  #if defined(_DELPHI_STRING_ONE_BASED)
      ThrowIfOutOfRange(idx);   // Should Range-checking be optional to avoid overhead ??
      Unique();                 // Ensure we're not ref-counted
      return Data[idx-1];
  #else
      ThrowIfOutOfRange(idx+1); // Should Range-checking be optional to avoid overhead ??
      Unique();                 // Ensure we're not ref-counted
      return Data[idx];
  #endif
    }

И как раз на основании его я предполагаю что с индексами строки (а кроме индексов строки в этой в ф-ии, где я обнаружил этот баг, никаких других неправильных работ с памятью вроде бы нет).

Ну т.е. AnsiString (я уже такое ловил) если хотя бы на единичку ошибешься в индексе - выбросит исключение.

Ну а дальше сами HexToBin (биндингов я не скопировал, т.к. они, судя по тому что выдал отладчик - написаны на Ассемблере)

function HexToBin(Text: PAnsiChar; Buffer: Pointer; BufSize: Integer): Integer;
begin
  Result := HexToBin(Text, PAnsiChar(Buffer), BufSize);
end;

далее

function HexToBin(Text: PAnsiChar; Buffer: PAnsiChar; BufSize: Integer): Integer;
var
  I: Integer;
  b1, b2: Byte;
begin
  I := BufSize;
  while I > 0 do
  begin
    b1 := H2BConvert[Ord(Text[0])];
    b2 := H2BConvert[Ord(Text[1])];
    if (b1 = $FF) or (b2 = $FF) then
      Break;
    Buffer[0] := AnsiChar((b1 shl 4) + b2);
    Inc(Buffer);
    Inc(Text, 2);
    Dec(I);
  end;
  Result := BufSize - I;
end;

Остальные ф-ии или не имеют открытой реализации или их не видит отладчик.

Ну т.е. в самой HexToBin не видно ничего плохого.

А вот такой теоритический вопрос.

Например ф-я foo() в которой нет ни одной ошибки в работе с памятью, вызывает ф-ю boo. boo принимает параметры по значению! Соответственно теоритически, даже если в boo есть какое-то биение памяти, но т.к. все ее переменные локальны по отношению к foo, и когда boo вернет результат своей работы, то может ли то что допустим внутри boo выделили память на куче, но при работе с ней залезли за кучу - как-то повлиять на foo?

bonta ★★★★ ()

Очевидно что HexToBin ломает стек.

Учитывая что она на паскакале, скорее всего проблема в том что она не правильно использует стек, будучи вызванной из плюсовой функции. То есть баг копилятора эмбракодело.

James_Holden ()
Ответ на: комментарий от James_Holden

Нет, это я невнимательный. Действительно дело в ней.. Вернее в том что я не правильно ее вызвал.

Всем спасибо.

Вот:

       const char firtSymbolFillers = std::abs(8 - firstSymbolPosIn7bit);

        if (UHDI_present && firtSymbolFillers) {
            unsigned char firstSymbol;
            HexToBin(&payloadText[1], &firstSymbol, 2);
        }

Видно что я вызываю ее с 2-йкой, двойка это сколько байтов читать. А передаю ей для сохранения переменную длинной в один байт.

И возможно _fastcall реализация конвекции о вызовах работает так что HexToBin берет в стеке переменную firstSymbol а коль ей нужно записать не один байт а два, то берет следующую переменную стека Inc(Buffer); - а это как раз константная firtSymbolFillers.

bonta ★★★★ ()
Последнее исправление: bonta (всего исправлений: 1)