LINUX.ORG.RU

Утечка памяти в простой проге.

 ,


1

2

написал утилитку, удаляющую все файлы wine из каталогов «/home/safff/.local/share/mime/application» и «/safff/.local/share/mime/packages».
все работает, только наблюдается утечка памяти. поначалу вроде ничего, килобайт 500, но потом разрастается за 10 минут в 2 метра+.
не пойму откуда ента утечка

★★

Последнее исправление: safocl (всего исправлений: 1)

компилировал с -std=c99

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

на баше есть.
учусь переписывая примеры утилит.

safocl ★★
() автор топика

в приличном обществе для каждой задачи используют самый простой и подходящий инструмент
бош скрипт для задачи наиболее верное решение
хочешь кодить на Си- так и пиши задачи для Си, а не эти непонятные костыли

не пытаюсь учить и навязывать, сам дойдешь до этого

anonymous
()

Ещё main() по стандарту должно возвращать int, а не void. Включи опцию компилятора -Wall, если используешь gcc.

aureliano15 ★★
()

Зачем ты в каждой итерации цикла заново компилируешь регулярное выражение? Вынеси компиляцию на самый верх и делай её один раз.

Legioner ★★★★★
()

написал утилитку, удаляющую все файлы wine из каталогов

#!/bin/sh

rm -fr "$HOME/.local/share/mime/application/path_to_wine"
rm -fr "$HOME/.local/share/mime/packages/path_to_wine"

И добавить ее в crontab.

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

Должно

Почему тогда в нижеследующей цитате допускается, что не int???

5.1.2.2.3 Program termination
1 If the return type of the main function is a type compatible with int, a return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument; reaching the } that terminates the main function returns a value of 0. If the return type is not compatible with int, the termination status returned to the host environment is unspecified.

anonymous
()

Какой ужас. Ты долбишься под указатель с памятью строк, но при этом перекомпелируешь регулярку на каждый цикол. Да и есть же strstr, если я правильно понял смысол регулярки. Строки можно было так:

char buffer[9999999999999999];
sprintf(buffer, "%s%s%s", "Simple", " ", "String append");
Да и память не надо было выделять, сделал бы просто
char path_buffer[OS_PATH_MAX];
for(;;) {
   ....
}

linuhs_user
()
Последнее исправление: linuhs_user (всего исправлений: 1)
Ответ на: комментарий от safocl

а зачем ты каждый раз компилируешь regexp? Он у тебя не меняется и соответственно его можно вынести на два цикла выше. так же match_1 должно прилетать из main параметров.

vtVitus ★★★★★
()

void main(void)

Итд

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

Откуда ты её высрал, эту цитату-то?

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

да, справедлива спс. исправлю.

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

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

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

ну чо бы не выделять лишнюю память, делаю войд.
просто я не парился по поводу чтения вывода ентой проги.
-Wall как я понял включает все варнинговые флаги? а чем она мне поможет? будет грить чо тип майна не инт?

safocl ★★
() автор топика
Последнее исправление: safocl (всего исправлений: 1)
Ответ на: комментарий от linuhs_user

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

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

да, уже указали выше, исправлю, спс

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

грят sprintf() медленнее чем memcpy()

Зато код короче, ты же не прошивку ракеты пишешь.

$ gcc main.c
$ time ./a.out memcpy
REPEAT: 65536

real	0m1,493s
user	0m0,046s
sys	0m0,251s

$ time ./a.out sprintf
REPEAT: 65536

real	0m1,508s
user	0m0,068s
sys	0m0,251s
В тесте сконекчивание 4 строк, 4 раза. «%s%s%s». Выполняется оно 65536 раз в цикле, посмотри на разницу, ее почти нет.

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

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

#include <linux/limits.h>

char current_path[PATH_MAX];

а так ты всегда выделяешь под необходимое количество символов размер.

char* str = ...;

char* buff;
int   buff_size;

buff_size = snprintf(NULL, 0, "%s%s", str, "hello");
buff = malloc(buff_size + 1);
sprintf(buff, "%s%s", str, "hello");
linuhs_user
()
Последнее исправление: linuhs_user (всего исправлений: 1)
Ответ на: комментарий от safocl
char* text = "hello";
text[0] = 'H'; /* segment fault */

лучше

const char* text = "hello";
text[0] = 'H'; /* Ошибка компиляции */

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

Массив для sprintf я же не всерьез, да и такое число в int не поместится.

фиксированные массивы

А смысл делать больше?

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

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

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

safocl ★★
() автор топика

не пойму откуда ента утечка

желтенькая утечка?

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

Ну так а на куче ты заюзаешь еще больше байтов чем сам массив, так как заголовок к куску итд. Плюс выделить на кучи это лишние такты!..)

linuhs_user
()
Последнее исправление: linuhs_user (всего исправлений: 1)
Ответ на: комментарий от alwayslate

Может лучше ты в интернет заходить не будешь? Фигею с лоровских `критиков`. И нет что бы сразу написать что не нравится, надо растянуть пару сообщений на страниц эдак 5-10.

linuhs_user
()
Последнее исправление: linuhs_user (всего исправлений: 1)
Ответ на: комментарий от linuhs_user

Фигею с лоровских `критиков`. И нет что бы сразу написать что не нравится, надо растянуть пару сообщений на страниц эдак 5-10.

еще один «гений», такие потом и придумывают всякие хипстоподелия вроде rust тк не могут понять где можно засрать в память.

последний раз для ... ну вы поняли, повторяю - НИКОГДА не надо юзать sprintf где есть неизвестной длинный указатели, юзайте всегда snprintf еще раз snprintf, тогда не промахнетесь мимо да.

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

Ты настолько ущербный что пытаешься хоть как то самоутвердиться наехав на рандом юзера с лора? Я вот даже не представляю кем нужно быть, серьезно, я такое только на ЛОРе вижу. Но чего ты ждешь? Что я не знаю о snprintf? Что для меня это за границой постижимого? Так а чего про массив ничего не сказал кстати? А? Ты же понимаешь что это псевдокод-намек, какая у тебя логика вообще?

А лучше покажи свой код, я уверен там не будет «плохих функций».)

linuhs_user
()
Последнее исправление: linuhs_user (всего исправлений: 2)
Ответ на: комментарий от linuhs_user

Ты настолько ущербный что пытаешься хоть как то самоутвердиться наехав на рандом юзера с лора? Я вот даже не представляю кем нужно быть, серьезно, я такое только на ЛОРе вижу. Но чего ты ждешь? Что я не знаю о snprintf? Что для меня это за границой постижимого? Так а чего про массив ничего не сказал кстати? А? Ты же понимаешь что это псевдокод-намек, какая у тебя логика вообще?

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

А лучше покажи свой код, я уверен там не будет «плохих функций».)

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

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

как я уже сказал, закончен

Так твои слова ничего не стоят) Скоро будет весна, будешь мух ловить и ими управлять, а то с людьми у тебя не получается.

НИКОГДА не надо юзать sprintf где есть неизвестной длинный указатели

У него кстати там известная длинна, а у меня в примере выше юзается snprintf для определения размера буфера, и ошибки вообще не может быть. Так же я показал snprintf, показал что он есть.

linuhs_user
()
Последнее исправление: linuhs_user (всего исправлений: 1)
Ответ на: комментарий от safocl

ну чо бы не выделять лишнюю память,

Лишняя память — это одна машинная инструкция по занесению 0 в нужный регистр перед выходом из main? Которая, к тому же, скорее всего всё равно будет добавлена компилятором?

делаю войд.

Тут анонимус процитировал стандарт 2011, где это допускается. Но в c99 и более ранних стандартах main() всегда должна возвращать int.

Кроме того, это полезно для пользователя программы, даже если ты всегда возвращаешь 0, т. к. оболочка может в случае ошибок возвратить другое значение в диапазоне от 0 до 255, что позволит отловить ошибку, если программа вызывается из скрипта (да и руками тоже). Подробнее читай здесь.

Ну и просто это считается хорошим стилем. void main() шокирует многих работодателей. Только из-за такой строчки тебе может быть отказано в работе, а твои свободные проекты могут быть проигнорированы, как «быдлокод».

-Wall как я понял включает все варнинговые флаги?

Да.

а чем она мне поможет? будет грить чо тип майна не инт?

И это тоже, но не только. Си — очень нестрогий язык, что часто приводит к труднообнаружимым ошибкам, особенно с массивами, указателями и динамически распределяемой памятью (взять, хотя бы, твой пример). Ворнинги предупреждают не обо всех, но о многих ошибках. Я очень рекомендую включать все ворнинги, внимательно их читать и исправлять. В общем, относиться к ним, как к ошибкам. В большинстве случаев это действительно логические ошибки. Если же это не так, то почти всегда можно написать такой же по смыслу, размеру (после компиляции) и эффективности код без них. Например, явно приводить типы. Это поможет и компилятору, и людям, читающим твою программу, и тебе самому впоследствии понять, чего ты хотел на самом деле. В редких случаях можно использовать прагмы для подавления ворнингов.

грят sprintf() медленнее чем memcpy()

Не нужно ловить блох, особенно когда учишься. Си и без того достаточно сложный язык. Сначала напиши понятную и работающую без ошибок программу. Потом, если производительность тебя не устраивает, прогони её через профилировщик, отлови узкие места и оптимизируй их. В твоём случае это будет то, что внутри цикла. И тебе уже указали на то, что регэкспресс ты компилируешь каждый раз заново. А почему ты сам это упустил? Отчасти потому, что сосредоточился на ловле блох (мнимая «экономия» на return и пр.)

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

В общем случае это так, но в твоём случае существуют константы из limits.h типа PATH_MAX и др., которые можно использовать, чтоб на этапе компиляции узнать максимальную длину пути.

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

Динамически распределяемой памятью тоже лучше не злоупотреблять без нужды. Во-первых, фактически выделяется немного больше, чем ты запросил (связано это с выравниванием и с сохранением служебной информации, необходимой malloc и free). Во-вторых, процесс выделения и освобождения этой памяти не бесплатен. Там используются списки, которые надо перестраивать, и это тоже влияет на производительность. В-третьих, всегда есть вероятность забыть освободить память или освободить её больше одного раза. Если максимальный размер в принципе заранее неизвестен или если он в разы больше, чем средний размер, то используй malloc, иначе делай так, как проще.

останутся неиспользованные байты.

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

чойт?

Не слушай его, человек не в теме.

linuhs_user, отличная шляпа! Где и почём покупал? Но в остальном прежняя аватарка была лучше, имхо.

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

Не советуйте плохое.

А где плохое?

Сишка

В си нет ничего плохого, и его никто не советовал ТС'у (по крайней мере здесь). ТС сам выбрал то, что хотел. И сделал правильный выбор.

и фиксированные массивы.

Фиксированные массивы — это нормально. Более того, это лучше, чем динамические массивы, в тех случаях, когда память под те или иные данные фиксирована.

Не советуйте плохое.

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

НИКОГДА не надо юзать sprintf где есть неизвестной длинный указатели,

Массивы, вы хотели сказать. Т. к. длина указателя вполне известна (4 или 8 байт в зависимости от разрядности ОС, 16-битные не рассматриваем).

И максимальная длина массива под путь в данном случае вполне известна. Она определяется константой PATH_MAX.

юзайте всегда snprintf

Вот давайте попробуем заюзать snprintf. Я автоматом удаляю старые ядра, имеющие имя /boot/vmlinuz.B*. Использую snprintf(). 2 байтиков мне не хватило, и вместо /boot/vmlinuz.B я удалил /boot/vmlinuz. И где эта ваша хвалёная безопасность snprintf? Уж лучше бы у меня программа сегфолтнулась, чем такая «безопасность». Да, я знаю, что по коду возврата всегда можно проверить, урезан буфер или нет. Но зачем, если linuhs_user проверяет это раньше? А мог бы и вообще не проверять, полагаясь на PATH_MAX.

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

О, уже старую вернул! Кстати, всегда интересовало, что там за кирпичи перед системником?

Шляпа у него одна, а вот рубашки интереснее))

Мне шляпа интереснее. Давно хотел купить консервативную фетровую, какие носили в 20 веке. Но в продаже только полуковбойские. У тебя тоже полуковбойская, но меня впечатлила. Шляпа из кожи, — такого я ещё не видел.

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

что там за кирпичи перед системником?

Наверное печенье или типо того.) Может верблюдика сверху ими подкармливает

У тебя тоже полуковбойская

У меня лично шляп к сожалению нету) Вроде Larry задавали вопросы про рубашки, я думаю он тебе и про шляпу ответит)

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