Неинициализированные блоки памяти в VC ++

Я написал этот класс, чтобы преодолеть проблему, которую я имел с выбором опции в списке выбора html. Я надеюсь, что это кому-то поможет.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace Login_page.Models
{
    public class HTMLSelect
    {
        public string id { get; set; }
        public IEnumerable<string> @class { get; set; }
        public string name { get; set; }
        public Boolean required { get; set; }
        public string size { get; set; }
        public IEnumerable<SelectOption> SelectOptions { get; set; }

        public HTMLSelect(IEnumerable<SelectOption> options)
        {

        }

        public HTMLSelect(string id, string name)
        {
            this.id = id;
            this.name = name;
        }

        public HTMLSelect(string id, string name, bool required, IEnumerable<SelectOption> options)
        {
            this.id = id;
            this.name = name;
            this.required = required;
        }

        private string BuildOpeningTag()
        {
            StringBuilder text = new StringBuilder();
            text.Append("<select");
            text.Append(this.id != null ? " id=" + '"' + this.id + '"' : "");
            text.Append(this.name != null ? " name=" + '"' + this.name + '"' : "");
            text.Append(">");
            return text.ToString();

        }

        public string GenerateSelect(IEnumerable<SelectOption> options)
        {
            StringBuilder selectElement = new StringBuilder();
            selectElement.Append(this.BuildOpeningTag());
            foreach (SelectOption option in options)
            {
                StringBuilder text = new StringBuilder();
                text.Append("\t");
                text.Append("<option value=" + '"' + option.Value + '"');
                text.Append(option.Selected != false ? " selected=" + '"' + "selected" + '"' + ">" : ">");
                text.Append(option.Text);
                text.Append("</option>");
                selectElement.Append(text.ToString());
            }
            selectElement.Append("</select");
            return selectElement.ToString();
        }
    }

    public class SelectOption
    {
        public string Text { get; set; }
        public Boolean Selected { get; set; }
        public string Value { get; set; }
    }
}

И

public IEnumerable<SelectOption> getOrderTypes()
{
    List<SelectOption> orderTypes = new List<SelectOption>();
                        if (this.orderType == "OptionText")
                        {
                            orderTypes.Add(new SelectOption() { Value = "1", Text = "OptionText", Selected = true });
                        } else
                        {
                            orderTypes.Add(new SelectOption() { Value = "2", Text = "OptionText2" });
                        }
}

И использовать его:

@{
    Login_page.Models.HTMLSelect selectElement = new Login_page.Models.HTMLSelect("order-types", "order-types");

}
@Html.Raw(selectElement.GenerateSelect(Model.getOrderTypes()));
5
задан LogicStuff 22 December 2015 в 23:07
поделиться

14 ответов

Это не ответственность delete сбрасывать все указатели на объект к NULL. Также Вы не должны изменять заполнение памяти по умолчанию для времени выполнения окон DEBUG, и необходимо использовать некоторую вещь как boost::shared_ptr<> для указателей любой путь.

Тем не менее, если Вы действительно хотите выстрелить Вашему сам в ногу, Вы можете.

Можно изменить заливку по умолчанию для времени выполнения окон DEBUG при помощи рычага средства выделения как это. Это будет только работать над "КУЧЕЙ" выделенный объект!

int main(int argc,char** arv)
{
  // Call first to register hook    
  _CrtSetAllocHook(&zero_fill);
  // Do other stuff
  malloc(100);
}


int zero_fill(int nAllocType, 
              void* pvData, 
              size_t nSize,
              int nBlockUse, 
              long lRequest, 
              const unsigned char *szFileName, 
              int nLine )
{
  /// Very Importaint !! 
  /// infinite recursion if this is removed !!
  /// _CRT_BLOCK must not do any thing but return TRUE
  /// even calling printf in the _CRT_BLOCK will cause
  /// infinite recursion
  if ( nBlockUse == _CRT_BLOCK )
    return( TRUE );
  switch(nAllocType)
  {
  case _HOOK_ALLOC:
  case _HOOK_REALLOC:
    // zero initialize the allocated space.
    memset(pvData,0,nSize);
    break;
  case _HOOK_FREE:
    break;
  }
  return TRUE;
}
6
ответ дан 18 December 2019 в 05:11
поделиться

Почему бы не создать Ваш собственный #define и привыкнуть использовать его?

Т.е.

#define SafeDelete(mem) { delete mem; mem = NULL; }
#define SafeDeleteArray(mem) { delete [] mem; mem = NULL; }

Очевидно, можно назвать его вообще, Вам нравится. удаляет, deletesafe, независимо от того, что Вы довольны.

0
ответ дан 18 December 2019 в 05:11
поделиться

при использовании malloc он не инициализирует память ни к чему. Вы добираетесь что. если Вы хотите выделить блок и инициализировать его к 0, используйте 'calloc', который похож на malloc только с инициализацией (параметр размера элемента, который Вы устанавливаете на 1, если Вы хотите эмулировать malloc). необходимо читать на calloc перед использованием его, поскольку это имеет некоторые незначительные различия.

http://wiki.answers.com/Q/What_is_the_difference_between_malloc_and_calloc_functions

0
ответ дан 18 December 2019 в 05:11
поделиться

Я вполне уверен, Вы не можете отключить значение по умолчанию Visual Studio здесь, и даже если бы Вы сделали, то значение затем было бы независимо от того, что было в памяти, прежде чем память была выделена.

Ваше лучшее от просто привыкания к установке их к 0 во-первых, это - только 2 дополнительных символа.

int *ptr=0;

Можно также использовать ПУСТОЙ макрос, который определяется как 0 (но не быть значением по умолчанию, так быть carful с повторными определениями, когда includeing наполняют как windows.h и определение его сами!

0
ответ дан 18 December 2019 в 05:11
поделиться

[Jeff Hubbard]:

То, что происходит, является моими катастрофическими отказами кода при компиляции отладки, но успешно выполняется при компиляции выпуска. Я проверил его под отладчиком, и мои указатели становятся установленными на 0xFEEEFEEE после того, как я буду звонить, удаляют на них. Снова, тот же код выпуска не отказывает и ведет себя как ожидалось.

Это - очень странное поведение - я все еще убежден, что существует, вероятно, скрытая ошибка, это скрыто _CrtSetAllocHook() обходное решение.

0xFEEEFEEE подпись используется диспетчером "кучи" ОС для указания на освобожденную память (см. http://www.nobugs.org/developer/win32/debug_crt_heap.html). Случайно можно ли отправить некоторый размноженный код и указать ли точно, какую версию компилятора Вы используете?

1
ответ дан 18 December 2019 в 05:11
поделиться

То, что происходит, является моими катастрофическими отказами кода при компиляции отладки, но успешно выполняется при компиляции выпуска.

Сборка конечных версий откажет на машине клиента. Это всегда делает.

Я проверил его под отладчиком, и мои указатели становятся установленными на 0xFEEEFEEE после того, как я звоню, удаляют на них.

Указатели не изменяются после вызова, удаляют на них. Это - память, на которую они указывают на это, установлен на 0xfeeefeee, 0xfeeefeee..., 0xfeeefeee.

Если Вы определяете ту свою программу, считывает данные с освобожденной памяти (который удобно обозначается 0xfeeefeee шаблоном в Отладочной сборке), у Вас есть ошибка.

3
ответ дан 18 December 2019 в 05:11
поделиться

Если это работает в режиме выпуска, это из-за удачи сдвига.

Mike B прав предположить, что фиксация отладки скрывает ошибку. В режиме выпуска указатель используется, который был освобожден, но не установлен на NULL, и память, на которую это указывает, все еще "допустима". В какой-то момент в будущем, выделения памяти изменятся, или отображение памяти изменится, или что-то заставит "допустимый" блок памяти становиться "недопустимым". В той точке Ваша сборка конечных версий начнет перестать работать. Переключение на режим отладки для нахождения проблемы будет бесполезно, потому что режим отладки был "зафиксирован".

Я думаю, что мы звоним, все соглашаются, что следующий код не должен работать.

char * p = new char[16];     // 16 bytes of random trash
strcpy(p, "StackOverflow");  // 13 characters, a '\0' terminator, and two bytes of trash
delete [] p;                 // return 16 bytes to the heap, but nothing else changes;

if (p != NULL)               // Why would p be NULL?  It was never set to NULL
    ASSERT(p[0] == 'S');     // In debug, this will crash, because p = 0xfeeefeee and 
                             // dereferencing it will cause an error.
                             // Release mode may or may or may not work, depending on
                             // other memory operations

Как примерно в любом плакате было сказано, указатели должны быть установлены на NULL после вызова delete. Делаете ли Вы это сами или используете повышение или некоторую другую обертку, или даже макрос в этом потоке ваше дело.

4
ответ дан 18 December 2019 в 05:11
поделиться

Вы говорите:

Я создаю и инициализирую переменную (через новый), и что все идет очень хорошо. Когда я освобождаю его (через, удаляют), это устанавливает указатель на 0xFEEEFEEE вместо ПУСТОГО УКАЗАТЕЛЯ. Когда я вставляю надлежащую проверку на ПУСТОЙ УКАЗАТЕЛЬ, как все хорошие программы, которые управляют их собственной памятью, должны, я придумать проблемы, поскольку 0xFEEEFEEE проходит ПУСТУЮ проверку без проблем.

Даже стандартные программы "кучи" отладки MSVC не изменят значение указателя, который Вы удаляете - значение указателя, который Вы удаляете, не изменится (даже на ПУСТОЙ УКАЗАТЕЛЬ). Это кажется на доступ к указателю, который принадлежит объекту, который Вы только что удалили, который является ошибкой, простой и простой.

Я вполне уверен, что то, что Вы пытаетесь сделать, просто покроет недопустимый доступ к памяти. Необходимо ли отправить отрывок кода, чтобы показать нам, что действительно происходит.

5
ответ дан 18 December 2019 в 05:11
поделиться

@Jeff Хаббард (комментарий):

Это на самом деле непреднамеренно предоставляет мне решение, которое я хочу: Я могу установить pvData в NULL на _HOOK_FREE и не столкнуться с проблемами с 0xFEEEFEEE для моего адреса указателя.

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

Это - ошибка.

'Решение', которое Вы используете, просто скрывается, не фиксация, ошибка. Когда та освобожденная память когда-либо будет выделена чему-то еще, внезапно Вы будете использовать неправильное значение в качестве указателя на неправильную вещь.

4
ответ дан 18 December 2019 в 05:11
поделиться

Если Вы создаете в режиме Release вместо Режима отладки, время выполнения не заполняет неинициализированную память вообще, но это все еще не будут нули. Однако Вы не должны зависеть от этого поведения - необходимо или явно инициализировать память сами с memset (), ZeroMemory (), или SecureZeroMemory (), или установить флаг, где-нибудь указывающий, что память еще не инициализируется. Чтение неинициализированной памяти приведет к неопределенному поведению.

6
ответ дан 18 December 2019 в 05:11
поделиться

При чтении неинициализированной памяти проверки несомненно не "допустимы". Память освобождена. Это могло бы уже использоваться для чего-то еще. Вы не можете сделать предположения о содержании неинициализированной памяти в C/C++.

Java (и C#, я верю), будет гарантируемый, что выделенная память обнуляется перед использованием, и конечно сборка "мусора" препятствует тому, чтобы Вы видели освобожденную память вообще. Но это не свойство "кучи" C, которая выставляет память непосредственно.

8
ответ дан 18 December 2019 в 05:11
поделиться

VC ++ поведение не должно вызывать опустошение ни с какой допустимой проверкой, которую можно сделать. Если Вы видите 0xfeeefeee затем, Вы не записали в память (или освободили его), таким образом, Вы не должны читать из памяти так или иначе.

14
ответ дан 18 December 2019 в 05:11
поделиться

При создании указателя explicity инициализируют его к NULL. Аналогично после a delete. В зависимости от значения неинициализированных данных (кроме нескольких конкретных случаев) напрашивается на неприятности.

Можно сохранить себя много головных болей при помощи класса интеллектуального указателя (такой как boost::shared_ptr) который будет автоматически иметь дело с тем, инициализируется ли указатель или нет.

17
ответ дан 18 December 2019 в 05:11
поделиться

Это - на самом деле очень хорошая функция в VC ++ (и я верю другим компиляторам), потому что он позволяет Вам видеть освобожденную память для указателя в отладчике. Я буду думать дважды прежде, чем отключить ту функциональность. При удалении объекта в C++, необходимо установить указатель на NULL в случае, если что-то более поздние попытки удалить объект снова. Эта функция позволит Вам определять места, где Вы забыли устанавливать указатель на NULL.

4
ответ дан 18 December 2019 в 05:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: