оказывается данный код в соответствии со стандартом. вызывает краш
...
free( p ) ;
if ( p == NULL ) // ..
Вид для печати
оказывается данный код в соответствии со стандартом. вызывает краш
...
free( p ) ;
if ( p == NULL ) // ..
Уверяю вас, в стандарте ничего нет про крэш. Там есть undefined behavior, но здесь я его не вижу, если p - валидный указатель на память, выделенную malloc и иже с ними.
ну етого хватает - в мане про cake php - потенциальный инжекшон прописан .....
[quote=Ull9;1994693]оказывается данный код в соответствии со стандартом. вызывает краш
...
free( p ) ;
if ( p == NULL ) // ..[/quote]
Думаю тут не в стандарте дело, просто неграмотно написанный код.
Должно быть вот так:
[code]
....
if (p)
{
free(p);
p = NULL;
}
.....
if (p == NULL)....
[/code]
Можно придумать и другие варианты, например safe pointers со счетчиком ссылок, кому как нравится...
[QUOTE=Newton;1997039]Думаю тут не в стандарте дело, просто неграмотно написанный код.
Должно быть вот так:
[code]
....
if (p)
{
free(p);
p = NULL;
}
.....
if (p == NULL)....
[/code]
Можно придумать и другие варианты, например safe pointers со счетчиком ссылок, кому как нравится...[/QUOTE]
в каком смысле неграмотный код?
компилятор его компилит, значит там грамматических ошибок нет.
да конечно в стандарте креша нет, как понятия, но это
именно UB.
обрашение к инвалидному пинтеру - это UB.
а так как предлагается исправить, то да UB не будет.
[QUOTE=Ull9;1997493]в каком смысле неграмотный код?
компилятор его компилит, значит там грамматических ошибок нет.
[/QUOTE]
Могу вас уверить,
можно написать миллион выражений с ошибками с точки зрения здравого смысла, которые спокойно прокомпилируются.
И целые толмуды описывают, как этого не делать.
Обнулять указатель после освобождения - это классика!
Хотите поиграться, начните с этого:
void f()
{
f();
}
Обычная рекурсия без выхода. Программа завалится по переполнению
стека. Но с точки зрения компиляции - абсолютно грамотная конструкция.
так вроде бы 2 есть ошибки .... например на яве - на собеседовании задают вопрос .....что будет //// бла бла бла
и выбирай
compilation error
runtime error
[QUOTE=lexar;2017298]
Обнулять указатель после освобождения - это классика!
.[/QUOTE]
обнулять пойнтер после освобождения конечно надо, но зачем.
лично для меня крэш здесь неожиданность.
я же непытаюсь вызвать метод по этому пойнтеру, или прочесть поле. я всего лишь сравнивваю с нулем!
я например этого незнал.
Язык какой?
Если на С, то проблем нет и быть не может, вполне допустимая конструкция, хотя и бессмысленная семантически.
free(p) не меняет значение p и никак не влияет на способы доступа к p - меняется доступ к *p.
Приведи выдержку из стандарта где это указано, если это С конечно.
C++, Stadard
3.7.3.2/4: "If the argument given to a deallocation function in the
standard library is a pointer that is not the null pointer value
(4.10), the deallocation function shall deallocate the storage
referenced by the pointer, rendering invalid all pointers referring to
any part of the deallocated storage. The effect of using an invalid
pointer value (including passing it to a deallocation function) is
undefined."
Все правильно и так же как и в С. В данном случае invalid pointer value - это не p, а *p.
И undefined effect будет если ты напишешь free(p); if(*p==NULL) ...
Не может free(p) поменять значение p.
Сравни с С:
[quote]
IEEE Std 1003.1, 2004 Edition
The free() function shall cause the space pointed to by ptr to be deallocated; that is, made available for further allocation. If ptr is a null pointer, no action shall occur. Otherwise, if the argument does not match a pointer earlier returned by the calloc(), malloc(), [ADV] [Option Start] posix_memalign(), [Option End] realloc(), or [XSI] [Option Start] strdup() [Option End] function, or if the space has been deallocated by a call to free() or realloc(), the behavior is undefined.
Any use of a pointer that refers to freed space results in undefined behavior.
[/quote]
[QUOTE=homo ludens;2030135]Все правильно и так же как и в С. В данном случае invalid pointer value - это не p, а *p.
И undefined effect будет если ты напишешь free(p); if(*p==NULL) ...
[/QUOTE]
а так же UB будет если написать
free (p);
if (p==0)
{
...
}
в этом то и весь прикол.
имхо, нет там такого прикола.
"The effect of using an invalid pointer value (including passing it to a deallocation function) is undefined."
ничего такого не подразумевает, что шло бы в разрез с общепринятыми понятиями - после освобождения блока не стоит разименовывать указатель и повторно его передавать в free.
не понял.
что значит разименовывать указатель?
и кто его повторно передает в free()?
поясни.
разименовывать - использовать память на которую указатель указывает.
1. int* pint;
2. pint=(int*)malloc(sizoef(int));
3. *pint=a;
4. b=*pint;
5. free(pint);
вот если строка 5 будет перед 3ей - вот тогда поведение строк 3 и 4 - undefined
два раза вызвать free на одном указателе - так тоже иногда бывает в жизни. баг, есс-но, но бывает. и вот поведение повторного вызова free - undefined.
не об этом ли говорит стандарт?
[QUOTE=Guffy;2031361]разименовывать - использовать память на которую указатель указывает.
1. int* pint;
2. pint=(int*)malloc(sizoef(int));
3. *pint=a;
4. b=*pint;
5. free(pint);
вот если строка 5 будет перед 3ей - вот тогда поведение строк 3 и 4 - undefined
два раза вызвать free на одном указателе - так тоже иногда бывает в жизни. баг, есс-но, но бывает. и вот поведение повторного вызова free - undefined.
не об этом ли говорит стандарт?[/QUOTE]
то о чем вы пишите действительно тривиально, но это совершенно не имеет отношения к тому что я написал. еще раз
void *p = malloc(1);
free (p);
if (p==0) // здесь возникает UB
{
...
}
здесь нет разименовывания (как вы определили) , здесь нет повторного освобождения памяти.
и это я назвал приколом.
код free(p); if(!p) ... абсолютно законен с точки зрения стандарта.
незаконен код free(p); if(!*p)
В стандарте С написано более просто.
[b]Any use of a pointer that refers to freed space results in undefined behavior.[/b]
А в С++ попробовали ужесточить и фраза стала чуть менее понятной.
[b]The effect of using an invalid pointer value (including passing it to a deallocation function) is undefined.[/b]
Реально написано одно и тоже, только разными словами.
Можно конечно прикопаться к термину using /any use и сказать, что любое упоминание в тексте (включая комментарии) имени переменной, после ее освобождения по free есть UB. :-)
Тогда твой пример действительно верен.
Я надеюсь, что авторы компиляторов все-таки не примут эту точку зрения, ну их нафиг такие приколы.
[QUOTE=homo ludens;2031400]код free(p); if(!p) ... абсолютно законен с точки зрения стандарта.
незаконен код free(p); if(!*p)
.[/QUOTE]
а также незаконен код free (p); if (!p)
[QUOTE=homo ludens;2031400]
В стандарте С написано более просто.
[b]Any use of a pointer that refers to freed space results in undefined behavior.[/b]
.[/QUOTE]
и этим все сказано.
все верно,
могу даже найти пример платформы где подобный код неизбежно вызывает UB
если бы это было верно
free (p);
if (p==0) // здесь возникает UB
это бы подразумевало, что free модифицирует содержимое переменной p (банально, как области памяти в 4 байта для 32битных систем).
однако
free(void* p) этого сделать не может.
он должен быть либо free(void** p) либо free(void*& p) /а референсов в С, если не ошибаюсь, нет. между тем free - функция именно С-рунтайма, а не С++ /
[QUOTE=Ull9;2031443]
могу даже найти пример платформы где подобный код неизбежно вызывает UB[/QUOTE]
ждемс