LINUX.ORG.RU

потому-что ошибки нет и ничего по указателю не считывается, проверяется только его значение (адрес) на неравенство нулю

MKuznetsov ★★★★★
()

А что тут невалидного. Может ты хочешь знать куда указывал i до того как был вызван free(i). Вот если бы было if (*i) - тогда другое дело, а так просто проверка на 0.

kpanic ★★
()

он и не должен это ловить, да и ошибки тут никакой нет, более того на if(i) всё рухнуть не может. обязательно рухнет только в случае if(*i) аргументация:

операция if(somevar) - делает исключительно логическую проверку. если бы получая указатель данная операция пыталась бы определить валидный он или нет - это был бы не C way.тк проверка валидности того или иного адреса - прерогатива и основа гарбидж коллектора, тк организовав такой механизм на кой чёрт нужна работа с памятью напрямую?

так что это вполне себе валидный код

asgard
()
Ответ на: комментарий от asgard

> да и ошибки тут никакой нет,

ошибка есть.

The value of a pointer that referred to an object whose storage is no longer reserved is indeterminate.

То есть значение _указателя_ неопределено. Использование (даже сравнение) неопределенного значения -- это undefined behaviour:

undefined behavior -- behavior, upon use of a nonportable or erroneous program construct, of erroneous data, or of indeterminately valued objects, for which this International Standard imposes no requirements

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

>ошибка есть.
>это undefined behaviour:

Для valgrind ошибки нет, потому что код даже обладающий
"undefined behaviour" в терминах стандарта,
собранный определенным компилятором с определенными флагами обладает уже defined behaviour.

fghj ★★★★★
()

бред. нет там никакой ошибки.

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

другое дело - проверка здесь абсолютно лишняя и бессмысленная конструкция. достаточно было просто занулить указатель без всякой проверки.

rip_someday
()
Ответ на: комментарий от fghj

> Для valgrind ошибки нет, потому что код даже обладающий
> "undefined behaviour" в терминах стандарта,
> собранный определенным компилятором с определенными флагами обладает уже defined behaviour.

У valgrind-а есть возможность проверять это, т.к. он отслеживает все переменные, в том числе и указатели. Тем более что подобные вещи, хоть и не приводят к ошибкам на x86, но абсолютно нелогичны, и скорее всего означают ошибку в программе (повисшую ссылку например).

Наверное в свободное время поковыряю его.


> бред. нет там никакой ошибки.

Пункт стандарта dilmah, спасибо ему, указал. С чем ты не согласен, со стандартом?

> указатель передается в free по значению. поменятся он не может никак. и неопределенным тоже стать не сможет. он остается ровно таким же каким он оказался после присваивания значения возвращенного malloc. неопеределенным будет значение которое лежит в памяти по адресу записанному в указателе. в коде значение никто не трогает, потому весь код будет строго определенным.

> другое дело - проверка здесь абсолютно лишняя и бессмысленная конструкция. достаточно было просто занулить указатель без всякой проверки.

Код - демонстрация моей мысли, особого смысла в нём нет.

Legioner ★★★★★
() автор топика
Ответ на: комментарий от Legioner

>Пункт стандарта dilmah, спасибо ему, указал. С чем ты не согласен, со стандартом?
это в каком таком месте переменная i может стать неопределенной?

int main(int argc,char **argv)
{
    int *i = (int*)malloc(sizeof(int));
    int *i1,*i2;
    i1 = i;
    free(i);
    i2 = i;

    if (i!=i1 || i!=i2)
        printf("Вселенная сошла с ума и мы уже ни в чем не можем быть уверены.\n");
    else
        printf("Мир пока еще в своем уме, а некоторым людям стоило бы покурить учебник по С и по английскому\n");
}

rip_someday
()

> всё может рухнуть

И что, существует конкретная платформа/компилятор, на которой исполнение данного кода приведет к падению?

Или это опять сферический конь в вакууме?

bigbit ★★★★★
()
Ответ на: комментарий от Legioner

вот и я в упор не понимаю, какого собственно чёрта всё должно рухнуть, если никакие операции, кроме разыменования, по адрусу указателя лезть не будут:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   int* i = (int*)malloc(sizeof(*i));

   printf("before: %p\n", i);
   free(i);

   printf("after: %p\n", i);

   return 0;
}

out:
before: 0x804a008
after: 0x804a008

asgard
()
Ответ на: комментарий от rip_someday

Однако я таки не прав. посыпаю голову пеплом.ISO C99 таки позволяет реализацию в которой при любом использовании указателя после вызова free может случиться фигня. хотя я бы за такое в стандарте ручки и ножки пообрывал бы.

rip_someday
()

Вот например тред на эту тему:
http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/7...

> As the OP wrote accessing the value of the pointer after deleting the
pointed-to object results in undefined behaviour. There's been many
threads about this in clc++m and a classic example is a 80386
compatible processor. The 80386 memory access model is quite
complicated and there are many ways to implement a "pointer".
One involves a pair (selector,offset) and loading a wrong selector
in any of the selector registers is an error (General Protection Fault
if I remember correctly). Deleting an object could result in freeing
the entry in a selector translation table and subsequent load of the
pointer value could fail.

Legioner ★★★★★
() автор топика
Ответ на: комментарий от Legioner

не тот случай, для проверки на нуль ничего такого делать не надо. просто идет сравнение значения в стеке с 0.
для gcc -arch=i386 :

080483d4 <main>:
 80483d4:	55                   	push   %ebp
 80483d5:	89 e5                	mov    %esp,%ebp
 80483d7:	83 ec 08             	sub    $0x8,%esp
 80483da:	83 e4 f0             	and    $0xfffffff0,%esp
 80483dd:	b8 00 00 00 00       	mov    $0x0,%eax
 80483e2:	83 c0 0f             	add    $0xf,%eax
 80483e5:	83 c0 0f             	add    $0xf,%eax
 80483e8:	c1 e8 04             	shr    $0x4,%eax
 80483eb:	c1 e0 04             	shl    $0x4,%eax
 80483ee:	29 c4                	sub    %eax,%esp
 80483f0:	83 ec 0c             	sub    $0xc,%esp
 80483f3:	6a 04                	push   $0x4
 80483f5:	e8 e6 fe ff ff       	call   80482e0 <malloc@plt>
 80483fa:	83 c4 10             	add    $0x10,%esp
 80483fd:	89 45 fc             	mov    %eax,0xfffffffc(%ebp)
 8048400:	83 ec 0c             	sub    $0xc,%esp
 8048403:	ff 75 fc             	pushl  0xfffffffc(%ebp)
 8048406:	e8 05 ff ff ff       	call   8048310 <free@plt>
 804840b:	83 c4 10             	add    $0x10,%esp
 804840e:	83 7d fc 00          	cmpl   $0x0,0xfffffffc(%ebp)
 8048412:	74 13                	je     8048427 <main+0x53>
 8048414:	83 ec 08             	sub    $0x8,%esp
 8048417:	ff 75 fc             	pushl  0xfffffffc(%ebp)
 804841a:	68 f8 84 04 08       	push   $0x80484f8
 804841f:	e8 dc fe ff ff       	call   8048300 <printf@plt>
 8048424:	83 c4 10             	add    $0x10,%esp
 8048427:	b8 00 00 00 00       	mov    $0x0,%eax
 804842c:	c9                   	leave  
 804842d:	c3                   	ret    
 804842e:	90                   	nop    
 804842f:	90                   	nop    

rip_someday
()
Ответ на: комментарий от rip_someday

Автор явно путает инструменты для статического анализа (static analysis tools), типа splint и иже с ними с инструментами для проверки во время выполнения (runtime checkers), типа valgrind. В данном случае (x86-32 и flat memory model) действительно никакой ошибки нет и valgrind совершенно правильно это не отлавливает.

anonymous
()
Ответ на: комментарий от anonymous

Может быть путаю.

Я рассуждаю так: valgrind нужен для отлова ошибок. Ошибка вполне рантаймовая, статическим анализом её можно обнаружить наверное только в простейшрих случаях. valgrind способен обнаружить такие ошибки (по крайней мере я не вижу причин, по которым он не способен делать это) - значит он должен это делать :)

Ладно, тему можно закрыть, я всё что хотел, выяснил.

Legioner ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.