Я написал этот класс, чтобы преодолеть проблему, которую я имел с выбором опции в списке выбора 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()));
Это не ответственность 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;
}
Почему бы не создать Ваш собственный #define и привыкнуть использовать его?
Т.е.
#define SafeDelete(mem) { delete mem; mem = NULL; }
#define SafeDeleteArray(mem) { delete [] mem; mem = NULL; }
Очевидно, можно назвать его вообще, Вам нравится. удаляет, deletesafe, независимо от того, что Вы довольны.
при использовании malloc он не инициализирует память ни к чему. Вы добираетесь что. если Вы хотите выделить блок и инициализировать его к 0, используйте 'calloc', который похож на malloc только с инициализацией (параметр размера элемента, который Вы устанавливаете на 1, если Вы хотите эмулировать malloc). необходимо читать на calloc перед использованием его, поскольку это имеет некоторые незначительные различия.
http://wiki.answers.com/Q/What_is_the_difference_between_malloc_and_calloc_functions
Я вполне уверен, Вы не можете отключить значение по умолчанию Visual Studio здесь, и даже если бы Вы сделали, то значение затем было бы независимо от того, что было в памяти, прежде чем память была выделена.
Ваше лучшее от просто привыкания к установке их к 0 во-первых, это - только 2 дополнительных символа.
int *ptr=0;
Можно также использовать ПУСТОЙ макрос, который определяется как 0 (но не быть значением по умолчанию, так быть carful с повторными определениями, когда includeing наполняют как windows.h и определение его сами!
[Jeff Hubbard]:
То, что происходит, является моими катастрофическими отказами кода при компиляции отладки, но успешно выполняется при компиляции выпуска. Я проверил его под отладчиком, и мои указатели становятся установленными на
0xFEEEFEEE
после того, как я буду звонить, удаляют на них. Снова, тот же код выпуска не отказывает и ведет себя как ожидалось.
Это - очень странное поведение - я все еще убежден, что существует, вероятно, скрытая ошибка, это скрыто _CrtSetAllocHook()
обходное решение.
0xFEEEFEEE
подпись используется диспетчером "кучи" ОС для указания на освобожденную память (см. http://www.nobugs.org/developer/win32/debug_crt_heap.html). Случайно можно ли отправить некоторый размноженный код и указать ли точно, какую версию компилятора Вы используете?
То, что происходит, является моими катастрофическими отказами кода при компиляции отладки, но успешно выполняется при компиляции выпуска.
Сборка конечных версий откажет на машине клиента. Это всегда делает.
Я проверил его под отладчиком, и мои указатели становятся установленными на 0xFEEEFEEE после того, как я звоню, удаляют на них.
Указатели не изменяются после вызова, удаляют на них. Это - память, на которую они указывают на это, установлен на 0xfeeefeee, 0xfeeefeee..., 0xfeeefeee.
Если Вы определяете ту свою программу, считывает данные с освобожденной памяти (который удобно обозначается 0xfeeefeee шаблоном в Отладочной сборке), у Вас есть ошибка.
Если это работает в режиме выпуска, это из-за удачи сдвига.
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
. Делаете ли Вы это сами или используете повышение или некоторую другую обертку, или даже макрос в этом потоке ваше дело.
Вы говорите:
Я создаю и инициализирую переменную (через новый), и что все идет очень хорошо. Когда я освобождаю его (через, удаляют), это устанавливает указатель на 0xFEEEFEEE вместо ПУСТОГО УКАЗАТЕЛЯ. Когда я вставляю надлежащую проверку на ПУСТОЙ УКАЗАТЕЛЬ, как все хорошие программы, которые управляют их собственной памятью, должны, я придумать проблемы, поскольку 0xFEEEFEEE проходит ПУСТУЮ проверку без проблем.
Даже стандартные программы "кучи" отладки MSVC не изменят значение указателя, который Вы удаляете - значение указателя, который Вы удаляете, не изменится (даже на ПУСТОЙ УКАЗАТЕЛЬ). Это кажется на доступ к указателю, который принадлежит объекту, который Вы только что удалили, который является ошибкой, простой и простой.
Я вполне уверен, что то, что Вы пытаетесь сделать, просто покроет недопустимый доступ к памяти. Необходимо ли отправить отрывок кода, чтобы показать нам, что действительно происходит.
@Jeff Хаббард (комментарий):
Это на самом деле непреднамеренно предоставляет мне решение, которое я хочу: Я могу установить pvData в NULL на _HOOK_FREE и не столкнуться с проблемами с 0xFEEEFEEE для моего адреса указателя.
Если это работает на Вас, то это означает чтение освобожденной памяти, когда Вы тестируете на Нулевого указателя (т.е., сам указатель находится в памяти, которую Вы освободили).
Это - ошибка.
'Решение', которое Вы используете, просто скрывается, не фиксация, ошибка. Когда та освобожденная память когда-либо будет выделена чему-то еще, внезапно Вы будете использовать неправильное значение в качестве указателя на неправильную вещь.
Если Вы создаете в режиме Release вместо Режима отладки, время выполнения не заполняет неинициализированную память вообще, но это все еще не будут нули. Однако Вы не должны зависеть от этого поведения - необходимо или явно инициализировать память сами с memset (), ZeroMemory (), или SecureZeroMemory (), или установить флаг, где-нибудь указывающий, что память еще не инициализируется. Чтение неинициализированной памяти приведет к неопределенному поведению.
При чтении неинициализированной памяти проверки несомненно не "допустимы". Память освобождена. Это могло бы уже использоваться для чего-то еще. Вы не можете сделать предположения о содержании неинициализированной памяти в C/C++.
Java (и C#, я верю), будет гарантируемый, что выделенная память обнуляется перед использованием, и конечно сборка "мусора" препятствует тому, чтобы Вы видели освобожденную память вообще. Но это не свойство "кучи" C, которая выставляет память непосредственно.
VC ++ поведение не должно вызывать опустошение ни с какой допустимой проверкой, которую можно сделать. Если Вы видите 0xfeeefeee затем, Вы не записали в память (или освободили его), таким образом, Вы не должны читать из памяти так или иначе.
При создании указателя explicity инициализируют его к NULL
. Аналогично после a delete
. В зависимости от значения неинициализированных данных (кроме нескольких конкретных случаев) напрашивается на неприятности.
Можно сохранить себя много головных болей при помощи класса интеллектуального указателя (такой как boost::shared_ptr
) который будет автоматически иметь дело с тем, инициализируется ли указатель или нет.
Это - на самом деле очень хорошая функция в VC ++ (и я верю другим компиляторам), потому что он позволяет Вам видеть освобожденную память для указателя в отладчике. Я буду думать дважды прежде, чем отключить ту функциональность. При удалении объекта в C++, необходимо установить указатель на NULL
в случае, если что-то более поздние попытки удалить объект снова. Эта функция позволит Вам определять места, где Вы забыли устанавливать указатель на NULL
.