LINUX.ORG.RU

Язык C и хорошая трава


0

0

Расскажите кто какую траву предпочитает ?
Ведь эти цитаты были рождены явно забористой дурью:

"Понимаешь что память виртуальная ядро может выделить память, а на самом деле ее может не оказаться - но это очень редко конечно но бывает, так что делать проверки это глупо это тебе не дос."

"префиксный инкремент быстрее постфиксного"


А также про неопределенное поведение i = i + 1
"Если i встречается (и изменяется) только с одной стороны от присваивания, то все в порядке"

anonymous

Первая цитата - совершенно правдивая. Ядро тебе mmap-ит блок, и всё. Ни за что не отвечает. Страницы виртуальной памяти будут выделены лишь при первой попытке обращения к ним. Так что проверка на результат выделения памяти ничего не даст.

flamer
()

>"Понимаешь что память виртуальная ядро может выделить память, а на самом деле ее может не оказаться - но это очень редко конечно но бывает, так что делать проверки это глупо это тебе не дос."

а тут все верно - и тут Си ни при чем =)

>"префиксный инкремент быстрее постфиксного"

ЗАвисит от контекста

>"Если i встречается (и изменяется) только с одной стороны от присваивания, то все в порядке"

Не совсем понятно что имелось в виду - хотя суть верная

Так что это ты траву куришь - все мозги затуманило =)

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

>Первая цитата - совершенно правдивая.
Ага хочешь сказать что нужно не проверять что возвратил malloc и преспокойно валится в корку вместо того чтобы корректно обработать этот момент ?

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

>>"префиксный инкремент быстрее постфиксного"
>ЗАвисит от контекста
Можно поподробнее ?

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

>Ага хочешь сказать что нужно не проверять что возвратил malloc и преспокойно валится в корку вместо того чтобы корректно обработать этот момент ?

ну проверишь что оно не нулл - обратишся а памяти не окажеться и будет тебе seg fault ;-) так что проверку делать бесмысленно только код больше станет.

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

>предпочитаю афганку. И лучше уж сразу хэш...
Как на счет молока ?

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

>ну проверишь что оно не нулл - обратишся а памяти не окажеться и будет >тебе seg fault ;-)
Ага вот только эта ситуация возможна только если в системе совсем кончилась память.
А как тебе такая ситуация:
есть некий конвертер файлов и предположим он вместо nmap грузит файло в память конвертит и сохраняет. У системы есть 100 свободных мегов.
Мы подсовываем конвертеру файлик на гиг.
Если мы обработаем то что возвращает malloc конвертер корректно завершится. Если не обработаем - segfault. Ну и что ты выбираешь ?

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

>а что имелось в виду?
пример того когда именно "префиксный инкремент быстрее постфиксного" :)

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

не смеши =) во первых - в данном случае размещать весь файл в памяти глупость - те говорит о плохом дизайне. во вторых такие случае не учитываем - или ты везде всегда проверяешь после malloc ? это кстати для новичков проверка после malloc - см исходный код к примеру gimp

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

>не смеши =) во первых - в данном случае размещать весь файл в памяти >глупость - те говорит о плохом дизайне.
Потребность в этом случается сплошь и рядом, пример с гипотетическим конвертером я привел тебе только для того чтобы показать что такая ситуация более чем реальна.

>во вторых такие случае не учитываем - или ты везде всегда проверяешь >после malloc ?
Везде и всегда - как отче наш ! Я больше скажу - я всегда и везде проверяю на корректность возвращаемые результаты всех функций которые могут как либо сигнализировать о неверном результате.
Может ты и после open результат не проверяешь ?

>это кстати для новичков проверка после malloc - см исходный код к >примеру gimp
Боже храни GNU/Linux ! Я очень хочу надеяться что это не так !

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

>Может ты и после open результат не проверяешь ?

это есстественно проверяеться, но как ты можешь проверить указатель не обратившись к нему - он не NULL будет - после того как ты к нему обратишся у тебя будет seg fault.

тут говориться только про результат malloc - а не open, не надо придумывать.

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

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

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

>Эта ситуация крайне маловероятна в отличие от той которую я тебе привел.

чтобы получить NULL - это тоже маловероятно - выводы делаешь сам =)

хотя конечно считаеться хорошим стилем написать свой -

mega-malloc()

и в нем делать проверку - только не вроде !=NULL а хитрее, иначе смысла нет.

alphex_kaanoken ★★★
()

>"префиксный инкремент быстрее постфиксного"

c.c: static int kk;

kk++; ++kk; printf("%d\n",kk);

#gcc -oc c.c #gdb ./c disassemble main

0x0804838c <main+0>: push %ebp 0x0804838d <main+1>: mov %esp,%ebp 0x0804838f <main+3>: sub $0x8,%esp 0x08048392 <main+6>: and $0xfffffff0,%esp 0x08048395 <main+9>: mov $0x0,%eax 0x0804839a <main+14>: add $0xf,%eax 0x0804839d <main+17>: add $0xf,%eax 0x080483a0 <main+20>: shr $0x4,%eax 0x080483a3 <main+23>: shl $0x4,%eax 0x080483a6 <main+26>: sub %eax,%esp 0x080483a8 <main+28>: incl 0x8049604 <<<<<<<<<<<<<<<< 0x080483ae <main+34>: incl 0x8049604 <<<<<<<<<<<<<<<< 0x080483b4 <main+40>: sub $0x8,%esp 0x080483b7 <main+43>: pushl 0x8049604 0x080483bd <main+49>: push $0x80484f8 0x080483c2 <main+54>: call 0x80482c0 <_init+56> 0x080483c7 <main+59>: add $0x10,%esp 0x080483ca <main+62>: mov $0x0,%eax да наверное быстрее.

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

> и в нем делать проверку - только не вроде !=NULL а хитрее, иначе
> смысла нет.

Твой код будет невозможно портировать.

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

А если программа ограничена через ulimit по объему памяти, то что вернет malloc()? Или по вашему это редкая ситуация? И потом, разве нету разницы как завершится программа, по segfault или нормально отработав ошибку?

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

>да наверное быстрее.
нет наверно не быстрее.

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

>А если программа ограничена через ulimit по объему памяти, то что >вернет malloc()? Или по вашему это редкая ситуация? И потом, разве нету >разницы как завершится программа, по segfault или нормально отработав >ошибку?
Конечно есть, вот только жаль что это не все присутсвующие понимают.

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

скорее всего имеется в виду С++ если перегружать операторы инкремента, то в случае постфиксного инкремента одновременно будут существовать два экземпляра (до и после)

k_andy ★★★
()

> "префиксный инкремент быстрее постфиксного"

в C - скорость одинаковая

а вот для C++ - действительно так, так как для выполнения постфиксного инкримента может потребоваться создание временного класса

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

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

проверка на невыделение памяти не имеет смысла только для rt аппликух ;)

lg ★★
()

>Понимаешь что память виртуальная ядро может выделить память, а на самом деле ее может не оказаться - но это очень редко конечно но бывает, так что делать проверки это глупо это тебе не дос."

Как не странно, но это написанно в man malloc :)

>А также про неопределенное поведение i = i + 1 "Если i встречается (и изменяется) только с одной стороны от присваивания, то все в порядке"

Скорее всего имелось ввиду многопоточное (multithread) приложение. Если в двух потоках эта строка не защищена например mutex-ом, то, если два потока выполнили эту строку последовательно, то значение i увеличилось на 2, а если они подошли одновременно, то второй поток может ссчитать значение i до того как первый успеет записать результат сложения.

>Расскажите кто какую траву предпочитает ? >Ведь эти цитаты были рождены явно забористой дурью:

Несовсем понятен вопрос. Если ещещ что почитать для начала, то IMHO лутше сначала взять любую печатную книгу, почитать, составить общее впечатленее, понят что тебе надо. Послее будет видно (для программирования по-моему лучше www.google.com+MSDN(если под Windows))

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

>во вторых такие случае не учитываем - или ты везде всегда проверяешь после malloc ? это кстати для новичков проверка после malloc - см исходный код к примеру gimp

Не стоит забывать, что есть и более другие ОС, под которые может быть перенесена программа. И вообще, закладываться на конкретную текущую реализацию, да еще гордиться этим, - это непрофессионально.

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

P.P.S. А насчет большего кода, Premature optimization is the root of all evils. Сначала надо научиться программы писать, а уж потом их оптимизировать.

WFrag ★★★★
()

2 автор темы

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

theSoul ★★★
()

гауно? гауно!

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

>а вот для C++ - действительно так
Мы про C говорим.

>так как для выполнения постфиксного инкримента может потребоваться >создание временного класса
Ты о чем ? По синтаксису это два метода (для префиксного инкремента и постфиксного), какой временный класс ?

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

>Как не странно, но это написанно в man malloc :)
Что именно ? В man malloc написано следующее:
"При неудаче выделения возвращается NULL."

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

>дело в том что невыделение памяти обычно не является критической >ошибкой, пока памяти нет выполнение таска(для которого нужна память) >откладывается на момент когда память появиться
Я надеюсь ты говришь о таком поведении самой программы а не принудительном STOP программы ядром (по типу неблокированного read) ?
Ибо вот пример который возвращает таки NULL не смотря на заявления некоторых высказавшихся выше:

xxx@xxx:~$ cat malloc_test.c
#include <stdio.h>
#include <string.h>
#include <errno.h>

int main()
{
for(;;)
{
size_t size = 10 * 1024 * 1024;
char *p = (char*)malloc(size);
if (p == NULL)
{
printf("ERROR: %s\n", strerror(errno));
return 1;
}
}
return 0;
}
xxx@xxx:~$ gcc malloc_test.c -o malloc_test
xxx@xxx:~$ ./malloc_test
ERROR: Cannot allocate memory
xxx@xxx:~$

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

>Видимо, народ здесь всё больше по синьке прикалывается
Если прикалывается то ладно, страшно если не прикалывается и указаний на ошибки не принемает, какой же там код ? :(
Но все таки не все такие я уверен...

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

>>так как для выполнения постфиксного инкримента может потребоваться >>создание временного класса

>Ты о чем ? По синтаксису это два метода (для префиксного инкремента и >постфиксного), какой временный класс ?

Не класс, а объект. Он наверное про http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.12

>>Как не странно, но это написанно в man malloc :) >Что именно ? В man malloc написано следующее: >"При неудаче выделения возвращается NULL."

Ой, а дочитать man страницу до раздела bugs или notes, несудьба. Если в дистрибутиве man страница действительно криваю, то можно посмотреть например здесь http://www.die.net/doc/linux/man/man3/malloc.3.html

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

конечно я говорю о поведении самой программы в случае отсутсвия памяти

кстати я не понял что такое принудительный STOP по типу неблокированного read?

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

> Ты о чем ? По синтаксису это два метода (для префиксного инкремента и постфиксного), какой временный класс ?

я имел ввиду экземпляр класса

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

>конечно я говорю о поведении самой программы в случае отсутсвия памяти
Те ты согласен что проверять возвращаемый malloc указатель на равенство NULL надо ? Ok.

>кстати я не понял что такое принудительный STOP по типу >неблокированного read?
man recv:
Если на сокете не доступно ни одного сообщения, то
обсуждаемые функции ожидают их прибытия, если сокет не
помечен как неблокирующий (см. fcntl(2)), в противном
случае возвращается значение -1, а внешняя переменная
errno устанавливается в значение EAGAIN.

С read на pipe то-же самое.

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

>Ибо вот пример который возвращает таки NULL не смотря на заявления некоторых высказавшихся выше:

Как ни странно пример не опровергает man страницу. Если malloc возвращает не NULL, то нет гарантии, что выделение памяти произошло. Про случай, когда malloc возвращает NULL в разделе bugs ничего не сказано. Всетаки man прочитать наверное стоит

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

>можно посмотреть например здесь >http://www.die.net/doc/linux/man/man3/malloc.3.html
Ты имеешь ввиду:
"Linux follows an optimistic memory allocation strategy. This means that when malloc() returns non-NULL there is no guarantee that the memory really is available. In case it turns out that the system is out of memory, one or more processes will be killed by the infamous OOM killer." ?
Такого в моем man malloc действительно нет, но я и раньше сказал что допускаю такую ситуацию, вот только вероятность ее возникновения несравнимо меньше возвращения NULL. Пример приведен выше, откомпили, запусти и убедись что malloc вернет NULL.

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

>Ты имеешь ввиду:

Да именно это.

>Пример приведен выше, откомпили, запусти и убедись что malloc вернет NULL.

Да, действительно NULL.

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

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main()
{
    for(;;)
    {
        size_t size = 10 * 1024 * 1024;
        char *p = ( char* ) malloc ( size );
        if ( p == NULL )
        {
            char *n = ( char* ) malloc ( size );
            if ( n == NULL )
            {
                n = "ERROR: ";
                printf ( "%s%s\n", n, strerror ( errno ) ) ;
                return 1;
            }
        }
    }
    return 0;
}

user 13:42:48 ~/malloc - gcc file.c -o file
user 13:45:16 ~/malloc - ./file
ERROR: Cannot allocate memory
user 13:45:18 ~/malloc -

А как такое обясним?

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

А вот если вот так

#include <stdlib.h>
#include <errno.h>

int main() 
{ 
	int i;
	for(i = 0; 1; ++i) 
	{ 
		size_t size = 10 * 1024 * 1024; 
		char *p = (char*)malloc(size); 
		if (p == NULL) 
		{ 
			printf("i = %d, ERROR: %s\n", i, strerror(errno)); 
			return 1; 
		} 
	} 
	return 0; 
} 

У меня 384Mb своп, 128Mb оперативки, а программа выводит i = 293

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

if ( p == NULL ) { char *n = ( char* ) malloc ( size ); if ( n == NULL ) { n = "ERROR: "; printf ( "%s%s\n", n, strerror ( errno ) ) ;

т.е : если "вроде бы маллок сказал что памяти нету" то пробуем выделить под указатель еще памяти и опять ноль, но записывается почему то в переменную данные и выводятся на stdout без Segmentation fulta и без корки. Как так?

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

>т.е : если "вроде бы маллок сказал что памяти нету" то пробуем выделить под указатель еще памяти и опять ноль, но записывается почему то в переменную данные и выводятся на stdout без Segmentation fulta и без корки. Как так?

"ERROR" - указатель на статическую область памяти, где храниться строка "ERROR" c завершающим нулем. Память была выделена до main.

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

Срочно книжки читать ... и вообще че тут развели? Хватит уже (8 . Все все поняли.

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

>А как такое обясним?
А зачем это объяснять ? Я просто показал что такая ситуация (когда malloc возвращает NULL) более чем возможна, а значит ДОЛЖНА быть обработана корректно. Мы ведь пишем работающие программы ? Задницей пускай дядя билл пишет.

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

> Те ты согласен что проверять возвращаемый malloc указатель на равенство NULL надо ? Ok.

так я про это и говорю, что проверять надо, т/к невыделение обычно(почти всегда) не является критической ошибкой

> Если на сокете не доступно ни одного сообщения, то обсуждаемые функции ожидают их прибытия, если сокет не помечен как неблокирующий (см. fcntl(2)), в противном случае возвращается значение -1, а внешняя переменная errno устанавливается в значение EAGAIN.

> С read на pipe то-же самое.

это то все понятно, ты просто так сформулировал("принудительный STOP по типу неблокированного read"), как будто это возникает ошибка, а на самом делето это не ошибка а поведение зареквестшеное через fcntl/ioctl

так что сравнение не совсем удачное. К томуже malloc обычно никогда не блокирует

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

>так я про это и говорю
вот-вот

>К томуже malloc обычно никогда не блокирует
вот-вот

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

Вот что написано в info libc:
If no more space is available, `malloc' returns a null pointer. You
should check the value of _every_ call to `malloc'.

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

Ты преспокойно свалишься в корку даже если "корректно" обработаешь результат malloc. Итак, ещё раз - бегом читать про mmap, и не позориться больше. Доступно?

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

Вот балбес... Да кто же тебе мешает при 100Мб свободных mmap-нуть гиговый файл? mmap-ай хоть до посинения, адресуйся к нему как хочешь... Ничего плохого не случится.

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