На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> c6001: использование неинициализированной памяти. Почему?
    Есть код:
    ExpandedWrap disabled
      int *x;
      ...
      x = new int[1000];
      ...
      if( ... )
      {
      ...
      }else
      {
        int xMinMax[2];
        xMinMax[0] = xMinMax[1] = x[0]; // здесь подчёркивает и пишет 'c6001: Использование неинициализированной памяти "*x"'
        ...
      }
    Пишет такое предупреждение (см. код). VisualStudio 2019. Отчего так?
      Вокруг
      ExpandedWrap disabled
        x = new int[1000];
      никаких условий нет??
      Все линейно??
        Потому что после new() для каждого элемента вызывается конструктор по-умолчанию. Для int он ничего не делает, в том числе и не обнуляет переменную. Поэтому каждый элемент этого массива остается непроинициализированным, т.е. содержит мусор, который был в куче на месте этого массива перед его созданием.
        Сообщение отредактировано: Dushevny -
          Цитата Dushevny @
          для каждого элемента вызывается конструктор по-умолчанию

          Хе-хе ... вопрос интересный! Что-то мне казалось, что для POD-типов нет ни конструкторов (не путать с аллокаторами), не их вызовов, ни по-умоланию и ваапще никак! И тут такой ответ, что я в тупике ... :-?

          Вызываю Qraizer'а!
          >:-[


          user posted image
            Цитата grgdvo @
            никаких условий нет??
            Все линейно??
            Да, всё именно банально так.

            Добавлено
            А, тьфу, всё понял! Это, как и написал Dushevny, оттого, что в x[0] то что-то кладётся по условия, а не всегда!
            ExpandedWrap disabled
              int *x;
              ...
              x = new int[1000];
              ...
              if( ... ) x[0] = ...;
              if( ... )
              {
              ...
              }else
              {
                int xMinMax[2];
                xMinMax[0] = xMinMax[1] = x[0]; // здесь подчёркивает и пишет 'c6001: Использование неинициализированной памяти "*x"'
                ...
              }


            Добавлено
            Цитата grgdvo @
            Вокруг
            ExpandedWrap disabled
              x = new int[1000];
            никаких условий нет??
            Получается, ошибся я, - есть условие 'вокруг'=после. Виноват-с... :blush:
              Славян, на какую именно строку идет "ругня"? Ты выдаешь такие "крохи" инфы, что просто приходится ломать спинной моск в попытках "угадать" >:(
              Ну что может быть проще привести весь проблемный код, и вывести все сообщения об ошибках и предупреждениях в первозданном виде?
              Не, без комментов далее ...

              Добавлено
              ADD: И даже после решения вопроса я не отказываюсь от своих "фу" и "фи" >:( 8-)
                Цитата Majestio @
                Что-то мне казалось, что для POD-типов нет ни конструкторов (не путать с аллокаторами), не их вызовов, ни по-умолчанию и ваапще никак!
                Что нет, что пустой и выкинутый оптимизатором по причине своей пустоты - для выходного кода результат одинаков. Может и есть исключение для POD-типов в стандарте - не помню, мне проще для себя для однообразия считать что конструктор есть, но пустой и потому соптимизированный.
                Сообщение отредактировано: Dushevny -
                  Цитата Majestio @
                  на какую именно строку идет "ругня"?
                  Строка приведена. Она вся подчёркивается волнистой.
                  Но суть то вся понята, ибо действительно x[0] то ли инициализировался, то ли нет - компилятор не знает, и вот на это использование и идёт ругань. Всё действительно просто.
                  Это как тривиальное:
                  ExpandedWrap disabled
                    int a;
                    int b = a;


                  Добавлено
                  Ну, чуть полнее, так:
                  ExpandedWrap disabled
                    int *x, k=0;
                    ...
                    x = new int[1000];
                    ...
                    if( ... ) x[k++] = ...;
                    if( !k )
                    {
                      ...
                    }else
                    {
                      int xMinMax[2];
                      xMinMax[0] = xMinMax[1] = x[0]; // здесь подчёркивает и пишет 'c6001: Использование неинициализированной памяти "*x"'
                      ...
                    }
                  Потому мне то вот понятно, что использован будет инициализированный элемент x[0], а машине - неведомо сие...
                    Цитата Славян @
                    Она вся подчёркивается волнистой.

                    Ну я на форуме обычно на все смотрю корпускулярно - не видны эти ваши красные волны! 8-)

                    Добавлено
                    Цитата Dushevny @
                    Что нет, что пустой и выкинутый оптимизатором по причине своей пустоты - для выходного кода результат одинаков.

                    Не не не - "точность - вежливость королей". Это нужно выяснить.
                      Ну конечно нет никаких конструкторов у POD. Но по факту это ничего не меняет.
                      В Стандарте определение объектов без инициализаторов называется default initialization и выполняется по-разному для классов и не-классов.
                      • Для классов вызывается конструктор по умолчанию. Если он не предоставлен программистом, он может быть сгенерирован компилятором. Если он не может быть сгенерирован, ошибка; если может, то он работает по тем же правилам инициализации для всех агрегированных объектов, т.е. все базовые объекты и поля инициализирует default initialization. Аналогично для массивов: default initialization для каждого элемента.
                      • Для не-классов ничего не выполняется. Это оставляет их в неизменном виде. Указатели являются не-классами.
                      • Ссылки и константные объекты не могут быть default initialization, это ошибка. Для агрегатов, содержащих в себе объекты этого типа, конструктор не может быть сгенерирован.
                      Но в Стандарте есть ещё такая штука, как zero initialization. Она не применяется к автоматическим и динамическим объектам, но если применяется, то до любой другой инициализации, в частности и default initialization. Т.к. для классов default initialization вполне себе инициализатор, хоть и зачастую неявный, то работу zero initialization можно увидеть только на статических и локальных в потоках объектах не-классах. И да, она забивает объект нулями. За исключением указателей, которые ставятся в nullptr. (Это на случай, если у вас nullptr не равен побитово целочисленному нулю ;). Ну а вдруг.) И да, включая pad-ы между полями агрегатов. А, ещё для ссылок есть исключение: zero initialization для них не выполняется, но т.к. они обязаны быть value initialized, то этого не видно.
                      Сообщение отредактировано: Qraizer -
                        Цитата Qraizer @
                        Ну конечно нет никаких конструкторов у POD. Но по факту это ничего не меняет.
                        В Стандарте определение объектов без инициализаторов называется default initialization и выполняется по-разному для классов и не-классов.
                        Для классов вызывается конструктор по умолчанию. Если он не предоставлен программистом, он может быть сгенерирован компилятором. Если он не может быть сгенерирован, ошибка; если может, то он работает по тем же правилам инициализации для всех агрегированных объектов, т.е. все базовые объекты и поля инициализирует default initialization. Аналогично для массивов: default initialization для каждого элемента.
                        Для не-классов ничего не выполняется. Это оставляет их в неизменном виде. Указатели являются не-классами.
                        Ссылки и константные объекты не могут быть default initialization, это ошибка. Для агрегатов, содержащих в себе объекты этого типа, конструктор не может быть сгенерирован.
                        Но в Стандарте есть ещё такая штука, как zero initialization. Она не применяется к автоматическим и динамическим объектам, но если применяется, то до любой другой инициализации, в частности и default initialization. Т.к. для классов default initialization вполне себе инициализатор, хоть и зачастую неявный, то работу zero initialization можно увидеть только на статических и локальных в потоках объектах не-классах. И да, она забивает объект нулями. За исключением указателей, которые ставятся в nullptr. (Это на случай, если у вас nullptr не равен побитово целочисленному нулю . Ну а вдруг.) И да, включая pad-ы между полями агрегатов. А, ещё для ссылок есть исключение: zero initialization для них не выполняется, но т.к. они обязаны быть value initialized, то этого не видно.

                        ЧТД, RTFM :-)
                        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                        0 пользователей:


                        Рейтинг@Mail.ru
                        [ Script execution time: 0,0997 ]   [ 16 queries used ]   [ Generated: 25.04.24, 03:47 GMT ]