Это лучше:
String::decode = ->
$('').html(this).text()
use:
"<img src='myimage.jpg'>".decode();
from: HTML Entity Decode
Установка неиспользуемых указателей в NULL - это защитный стиль, защищающий от ошибок висящих указателей. Если к висячему указателю обращаются после его освобождения, вы можете прочитать или перезаписать случайную память. Если осуществляется доступ к нулевому указателю, вы получаете немедленный сбой в большинстве систем, сразу же сообщая вам, в чем заключается ошибка.
Для локальных переменных это может быть немного бессмысленным, если «очевидно», что указатель неверный. t больше не доступен после освобождения, поэтому этот стиль больше подходит для данных-членов и глобальных переменных. Даже для локальных переменных это может быть хорошим подходом, если функция продолжится после освобождения памяти.
Чтобы завершить стиль, вы также должны инициализировать указатели на NULL, прежде чем им будет присвоено истинное значение указателя.
Это может быть больше аргументом для инициализации всех указателей на NULL, но что-то вроде этого может быть очень скрытой ошибкой:
void other_func() {
int *p; // forgot to initialize
// some unrelated mallocs and stuff
// ...
if (p) {
*p = 1; // hm...
}
}
void caller() {
some_func();
other_func();
}
p
заканчивается в том же месте в стеке как и бывший nPtr
, поэтому он все еще может содержать, казалось бы, действительный указатель. Назначение * p
может перезаписать все виды несвязанных вещей и привести к некрасивым ошибкам. Особенно, если компилятор инициализирует локальные переменные нулем в режиме отладки, но не после включения оптимизации. Таким образом, отладочные сборки не показывают никаких признаков ошибки, в то время как релизные сборки взрываются случайным образом ...
В дополнение к сказанному другими, один хороший метод использования указателя - всегда проверять, является ли указатель действительным или нет. Что-то вроде:
if(ptr)
ptr->CallSomeMethod();
Явная пометка указателя как NULL после освобождения позволяет такое использование в C / C ++.
Это правило полезно, когда вы пытаетесь избежать следующих сценариев:
1) У вас действительно длинная функция со сложной логикой и управлением памятью, и вы не хотите случайно повторно используйте указатель на удаленную память позже в функции.
2) Указатель является переменной-членом класса, который имеет довольно сложное поведение, и вы не хотите случайно повторно использовать указатель на удаленную память в других функциях.
В вашем сценарии это не имеет большого смысла, но если функция станет длиннее, это может иметь значение.
Вы можете возразить, что установка ее на NULL может фактически замаскировать логические ошибки позже или в в случае, когда вы предполагаете, что он действителен, вы все равно вылетаете на NULL, поэтому это не имеет значения.
В общем, я бы посоветовал вам установить значение NULL, если вы думаете, что это хорошая идея, и не беспокойтесь, когда думаете, что оно того не стоит. Вместо этого сосредоточьтесь на написании коротких функций и хорошо спроектированных классов.
Это (может) действительно важно. Хотя вы освобождаете память, более поздняя часть программы может выделить что-то новое, что случайно попадает в пространство. Ваш старый указатель теперь будет указывать на действительный кусок памяти. Тогда возможно, что кто-то будет использовать указатель, что приведет к недопустимому состоянию программы.
Если вы обнуляете указатель, то любая попытка его использования приведет к разыменованию 0x0 и сбою прямо здесь, что легко отладить. Случайные указатели, указывающие на случайную память, сложно отлаживать. Очевидно, в этом нет необходимости, но именно поэтому это указано в документе о передовых методах работы.
Идея состоит в том, чтобы остановить случайное повторное использование освобожденного указателя.
Установка указателя на свободную
d память означает, что любая попытка доступа к этой памяти через указатель приведет к немедленному сбою, вместо того, чтобы вызывать неопределенное поведение. Это значительно упрощает определение того, где что-то пошло не так.
Я вижу ваш аргумент: поскольку nPtr
выходит из области видимости сразу после nPtr = NULL
, нет кажется причиной установить его на NULL
. Однако в случае элемента struct
или где-то еще, где указатель не сразу выходит за пределы области видимости, это имеет больше смысла. Не сразу ясно, будет ли этот указатель снова использоваться кодом, который не должен его использовать.
Вероятно, правило сформулировано без различия между этими двумя случаями, потому что гораздо сложнее автоматически обеспечить соблюдение правила, не говоря уже о том, чтобы разработчики следовали ему. Не повредит установить указатели на NULL
после каждого освобождения, но это может указать на большие проблемы.
Если вы дойдете до указателя, который был free () d, он может сломаться или нет. Эта память может быть перераспределена в другую часть вашей программы, и тогда вы получите повреждение памяти,
Если вы установите указатель на NULL, то при доступе к нему программа всегда вылетает с ошибкой segfault. Больше нет, иногда это работает, не больше, вылетает непредсказуемым образом ». Так проще отлаживать.
Это хороший способ избежать перезаписи памяти. В приведенной выше функции в этом нет необходимости, но часто, когда это делается, можно обнаружить ошибки приложения.
Попробуйте вместо этого что-нибудь вроде этого:
#if DEBUG_VERSION
void myfree(void **ptr)
{
free(*ptr);
*ptr = NULL;
}
#else
#define myfree(p) do { void ** __p = (p); free(*(__p)); *(__p) = NULL; } while (0)
#endif
DEBUG_VERSION позволяет вам профилировать освобождение при отладке кода, но оба функционально одинаковы.
Правка : Добавлен do ... пока как предлагается ниже, спасибо.
Settings a pointer to NULL is to protect agains so-called double-free - a situation when free() is called more than once for the same address without reallocating the block at that address.
Double-free leads to undefined behaviour - usually heap corruption or immediately crashing the program. Calling free() for a NULL pointer does nothing and is therefore guaranteed to be safe.
So the best practice unless you now for sure that the pointer leaves scope immediately or very soon after free() is to set that pointer to NULL so that even if free() is called again it is now called for a NULL pointer and undefined behaviour is evaded.
Установка только что освобожденного указателя на NULL не обязательно, но рекомендуется. Таким образом, вы можете избежать 1) использования заостренного конуса 2) заострения руки
From the ANSI C standard:
void free(void *ptr);
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc , malloc , or realloc function, or if the space has been deallocated by a call to free or realloc , the behavior не определено.
«Неопределенное поведение» почти всегда означает сбой программы. Чтобы избежать этого, можно безопасно сбросить указатель на NULL. Сам free () не может этого сделать, поскольку ему передается только указатель, а не указатель на указатель. Вы также можете написать более безопасную версию free (), которая обнуляет указатель:
void safe_free(void** ptr)
{
free(*ptr);
*ptr = NULL;
}
наиболее распространенная ошибка в c - это двойное освобождение. Обычно вы делаете что-то вроде этого
free(foobar);
/* lot of code */
free(foobar);
, и это заканчивается очень плохо, ОС пытается освободить некоторую уже освобожденную память, и обычно это происходит с ошибкой. Поэтому рекомендуется установить значение NULL
, чтобы вы могли провести тест и проверить, действительно ли вам нужно освободить эту память
if(foobar != null){
free(foobar);
}
. Также следует отметить, что free (NULL)
выиграл 'ничего не делайте, поэтому вам не нужно писать оператор if. Я не совсем гуру ОС, но я довольно даже сейчас, что большинство ОС вылетали бы при двойном освобождении.
Это также основная причина, по которой все языки со сборкой мусора (Java, dotnet) так гордились тем, что у них нет этой проблемы, а также не приходится передавать разработчикам управление памятью в целом.
Я считаю, что это мало помогает, так как по моему опыту, когда люди обращаются к освобожденному распределению памяти, это почти всегда потому, что у них где-то есть другой указатель на него. А затем он конфликтует с другим персональным стандартом кодирования, который называется «Избегайте бесполезного беспорядка», поэтому я не делаю этого, поскольку считаю, что это редко помогает и делает код менее читабельным.
Однако - я не буду устанавливать переменную значение null, если указатель не предполагается использовать снова, но часто дизайн более высокого уровня дает мне причину установить его в любом случае. Например, если указатель является членом класса, и я удалил то, на что он указывает, тогда «контракт» класса, если вам нравится, заключается в том, что этот член будет указывать на что-то действительное в любое время, поэтому он должен быть установлен на null по этой причине. Небольшое отличие, но я считаю важным.
В C ++ важно всегда думать, кому принадлежат эти данные, когда вы выделяете некоторую память (если вы не используете интеллектуальные указатели, но даже в этом случае требуется некоторое размышление). И этот процесс имеет тенденцию приводить к тому, что указатели обычно являются членами некоторого класса, и обычно вы хотите, чтобы класс всегда находился в допустимом состоянии, и самый простой способ сделать это - установить для переменной-члена значение NULL, чтобы указать, что она указывает
Распространенным шаблоном является установка всех указателей на элементы в NULL в конструкторе и удаление с помощью вызова деструктора любых указателей на данные, которые, согласно вашему проекту, принадлежат классу . Очевидно, что в этом случае вам нужно установить указатель на NULL, когда вы что-то удаляете, чтобы указать, что вы не владеете какими-либо данными раньше.
Итак, чтобы подвести итог, да, я часто устанавливаю указатель на NULL после удаления чего-либо, но это как часть более крупного проекта и размышлений о том, кто владеет данными, а не из-за слепого следования стандартному правилу кодирования. Я бы не стал этого делать в вашем примере, поскольку считаю, что это бесполезно, и это добавляет «беспорядок», который, по моему опыту, так же ответственен за ошибки и плохой код, как и подобные вещи.
Есть две причины:
Автор RageZ в повторяющемся вопросе .
Самая распространенная ошибка в c - двойной бесплатно. В основном вы делаете что-то вроде что
бесплатно (foobar); / * много кода * / бесплатно (foobar);
и все закончилось плохо, ОС попробуйте чтобы освободить уже освобожденную память и в общем это segfault. Так что хорошо практика - установить значение
NULL
, поэтому вы может сделать тест и проверить, действительно ли вы необходимо освободить эту памятьif (foobar! = NULL) { бесплатно (foobar); }
также следует отметить, что
бесплатно (NULL)
ничего не будет делать, так что вам не нужно напишите оператор if. не я действительно гуру ОС, но я довольно даже теперь большинство ОС вылетали бы при двойном бесплатно.Это также основная причина, почему все языки со сборкой мусора (Java, dotnet) так гордился тем, что имея эту проблему, а также нет вынужден оставить разработчику управление памятью в целом.
Написано Мартином фон Лёвисом в другом ответе .
Установка неиспользуемых указателей в NULL является защитный стиль, защита от ошибки висячих указателей. Если болтается к указателю обращаются после его освобождения, вы можете читать или перезаписывать случайные объем памяти. Если осуществляется доступ к нулевому указателю, вы получаете немедленный сбой на большинстве системы, сразу сообщая вам, что ошибка.
Для локальных переменных это может быть немного бессмысленно, если это "очевидно", что указатель не доступ больше после освобождения, поэтому этот стиль больше подходит для данные-члены и глобальные переменные. Даже для локальных переменных это может быть хорошим подход, если функция продолжается после освобождения памяти.
Для завершения стиля вы также должны инициализировать указатели на NULL перед им присваивается настоящий указатель значение.
Большинство ответов было сосредоточено на предотвращении двойного освобождения, но установка указателя на NULL имеет еще одно преимущество. Как только вы освободите указатель, эта память станет доступной для перераспределения другим вызовом malloc. Если у вас все еще есть исходный указатель, вы можете столкнуться с ошибкой, когда вы пытаетесь использовать указатель после освобождения и повреждения какой-либо другой переменной, а затем ваша программа переходит в неизвестное состояние, и могут произойти всевозможные плохие вещи (сбой, если вы повезло, данные порча если не повезло). Если вы установили указатель на NULL после освобождения, любая попытка чтения / записи через этот указатель позже приведет к segfault, что обычно предпочтительнее случайного повреждения памяти.
По обеим причинам может быть хорошей идеей установите указатель в NULL после free (). Однако это не всегда необходимо.
Установка указателя на NULL
после бесплатно
- сомнительная практика, которая часто популяризируется как правило «хорошего программирования» на заведомо ложной предпосылке. Это одна из тех фальшивых истин, которые относятся к категории «звучит правильно», но на самом деле не дают абсолютно ничего полезного (а иногда и приводят к негативным последствиям).
Предполагается, что установка указателя на NULL
после free
должна предотвратить ужасную проблему «двойного освобождения», когда то же значение указателя передается в free
больше чем единожды. На самом деле, в 9 случаях из 10 настоящая проблема «двойного освобождения» возникает, когда разные объекты-указатели, содержащие одно и то же значение указателя, используются в качестве аргументов для освобождения
. Излишне говорить, что установка указателя на NULL
после free
абсолютно ничего не дает для предотвращения проблемы в таких случаях.
Конечно, можно столкнуться с "двойным освобождением" проблема при использовании того же объекта-указателя в качестве аргумента free
. Однако, в действительности подобные ситуации обычно указывают на проблему с общей логической структурой кода, а не на случайное «двойное освобождение». Правильный способ решения проблемы в таких случаях - это пересмотреть и переосмыслить структуру кода, чтобы избежать ситуации, когда один и тот же указатель передается в free
более одного раза. В таких случаях установка указателя на NULL
и рассмотрение проблемы «исправленной» - это не более чем попытка скрыть проблему. Это просто не сработает в общем случае, потому что проблема со структурой кода всегда найдет другой способ проявить себя.
Наконец, если ваш код специально разработан, чтобы полагаться на значение указателя, равное NULL
или нет NULL
, совершенно нормально установить значение указателя на NULL
после free
. Но в качестве общего правила «хорошей практики» (например, «всегда устанавливайте указатель на NULL
после free
») это, опять же, хорошо известная и довольно бесполезная подделка, за ними часто следуют чисто религиозные, похожие на вуду причины.