URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 3929
[ Назад ]

Исходное сообщение
"проблемы с памятью ;)"

Отправлено maverick , 08-Фев-05 19:46 
Я программирую под Linux (2.4.22) на си, используя компилятор gcc 3.4.3
Посоветуйте самый безглючный способ инициализации памяти:
1) объявить static char *buffer; затем в main(): buffer = (char *) calloc(SIZE, 1); а в подключаемых файлах писать extern char *buffer;

2) объявить в каждом из файлов свой static char *buffer; в каждой функции
писать buffer = (char *) calloc(SIZE, 1); а затем free(buffer);

Просто блин эти сегфолты действуют на нервы...

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


Содержание

Сообщения в этом обсуждении
"проблемы с памятью ;)"
Отправлено DeadMustdie , 09-Фев-05 11:02 
>Я программирую под Linux (2.4.22) на си, используя компилятор gcc 3.4.3
>Посоветуйте самый безглючный способ инициализации памяти:
> 1) объявить static char *buffer; затем в main(): buffer = (char
>*) calloc(SIZE, 1); а в подключаемых файлах писать extern char *buffer;

Не должно даже линковаться. Переменные класса static не видны за
пределами модуля трансляции (в простейшем случае - c-файла), в
котором они объявлены.

>
> 2) объявить в каждом из файлов свой static char *buffer; в
>каждой функции
>писать buffer = (char *) calloc(SIZE, 1); а затем free(buffer);
>

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

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

> Просто блин эти сегфолты действуют на нервы...
>

Они не сами по себе возникают. Вообще SIGSEGV - вещь крайне полезная.
Позволяет быстро найти идиотские ошибки.

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

Если версия GLIBC с ядром не дружит (например, GLIBC сильно старая,
а ядро сильно новое), возможны кое-какие проблемы. Редко, но бывает.
В основном при использовании функций трассировки другого процесса,
установке ловушек (trap) и работе с pthread'ами.


"проблемы с памятью ;)"
Отправлено maverick , 09-Фев-05 20:47 

>Не должно даже линковаться. Переменные класса static не видны за
>пределами модуля трансляции (в простейшем случае - c-файла), в
>котором они объявлены.
>

То есть как это не видны? Видны. Иначе зачем вообще такая фича как
extern ?

>>
>> 2) объявить в каждом из файлов свой static char *buffer; в
>>каждой функции
>>писать buffer = (char *) calloc(SIZE, 1); а затем free(buffer);
>
>Лучше по мере надобности память в оных функциях выделять, а по
>окончании оной надобности - освобождать.
>

Допустим мне надо создать в программе три часто исплользуемых буфера.
Дак что же, мне придётся тогда в каждой подпрограмме их объявлять, аллокейтить, юзать, а потом освобождать? Как-то гиморно.. Неужели нельзя сделать всё первым способом?


"проблемы с памятью ;)"
Отправлено Xenu , 09-Фев-05 22:01 
>
>>Не должно даже линковаться. Переменные класса static не видны за
>>пределами модуля трансляции (в простейшем случае - c-файла), в
>>котором они объявлены.
>>
>
>То есть как это не видны? Видны. Иначе зачем вообще такая фича
>как
>extern ?
Как это возможно, что static переменная объявленная в одном файле видно из другого файла.
Не покажите ли что линкер напечатал при собирании такого кода.

extern служит не для того что бы static переменные в другом файле использовать.

>>>
>>> 2) объявить в каждом из файлов свой static char *buffer; в
>>>каждой функции
>>>писать buffer = (char *) calloc(SIZE, 1); а затем free(buffer);
>>
>>Лучше по мере надобности память в оных функциях выделять, а по
>>окончании оной надобности - освобождать.
>>
>
>Допустим мне надо создать в программе три часто исплользуемых буфера.
>Дак что же, мне придётся тогда в каждой подпрограмме их объявлять, аллокейтить,
>юзать, а потом освобождать? Как-то гиморно.. Неужели нельзя сделать всё первым
>способом?
объявите 3 буфера или один. но только обращайтесь к ним через функции доступа и не пишите напрямую в буфера из других мест.


"проблемы с памятью ;)"
Отправлено dimus , 10-Фев-05 12:36 
Я пришел к выводу, что оптимальным вариантом во многих случаях является использование подхода, подобного классам в С++. Напишите семейство функций, внутри которых идет работа с этим буфером, как с ЗАКРЫТЫМ объектом. Пусть ничто из внешнего мира не обращается к нему иначе, чем через них. Тогда если ошибки и возникнут, их можно будет очень легко отследить и ликвидировать.

typedef struct _tagBUF
{
void* buf;
int buf_size;
// И т.д.
} BUF;
// "Конструктор"
int buf_init( BUF* p_buf, void* buf, int buffer_size /*И т.д.*/);
// Полезные функции, например
void buf_clear( BUF* p_buf )
{
memset( p_buf -> buf, 0, p_buf -> buf_size );
}
и т.д.
Лично я в последнее время стараюсь неукоснительно следовать этому подходу, и я заметил, что так совершаешь гораздо меньше ошибок.

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


"проблемы с памятью ;)"
Отправлено DeadMustdie , 10-Фев-05 13:08 
>Мне могут указать, что можно сразу использовать С++ и не парится. Если

Возникает. Жизнь слишком коротка, чтобы лишний раз париться :).

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

А не всё ли равно? Если по каким-то причинам нужно недекорированное
имя, к нему всегда можно приписать extern "C".


"проблемы с памятью ;)"
Отправлено dimus , 10-Фев-05 13:36 
Из ассемблера?

"проблемы с памятью ;)"
Отправлено DeadMustdie , 10-Фев-05 16:35 
>Из ассемблера?

extern "C" int myIntValForAsmAccess;
extern "C" int myFyncForAsmAccess(int a, int b);