Как отмаллочить память для элемента структуры в Си?
Можно выделять статически, в сегменте данных. Или в куче.
Под char * выделять очень просто:
И прочитать-таки книжку про язык C.
dat4 = (char *)malloc(N);
if (dat4 == NULL) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
А насчёт стека... он же как-то выделяется из оперативной памяти? Так оперативки-то не используемой в этот момент дохрена
Выделить место для dat4 ( ( i >= 0 ) && ( i <= number - 1 ) ):
#include <stdlib.h>
...
struct out date[number];
В C память нужно освобождать вручную:
date[i].dat4 = ( char * ) calloc ( n, sizeof( char ) );
if ( date[i].dat4 == NULL ) { do_something_on_error; }
Да, нужно всё делать для каждого элемента dat4 структур, в цикле
free( date[i].dat4 ); date[i].dat4 = NULL;
Да, нужно выделять для всех элементов структуры, в циклеПипец какой-то, у меня в структурах этих элементов двадцать с лишним, и у каждого уникальное название
Во многих системах есть ограничение на размер стека, и по умолчанию максимальный размер не очень большой.
В системе всего гигабайт, слакварь, у меня права обычного юзера.
Думаешь, не хватает?
это если треды не используются
Ок, спасибо, пойду ботать
for (k = 1; k <= number; k++)
for (k = 0; k < number; k++)
Пипец какой-то, у меня в структурах этих элементов двадцать с лишнимПросто начни программировать на С++. Там есть std::string.
struct dat
{
int a;
float b;
double c;
float *m;
...
};
dat *d;
d = (dat*) malloc(num*sizeof(dat;
for (i=0;i<num;i++)
d.m[i] = (float*) malloc(m_num*sizeof(float;
...
for (i=0;i<m_num;i++)
free(d.m[i]);
free(d);
{т.е. массив ссылок на объекты struct dat}
потом напиши:
for(i:=0 i<number; i++) date[ i ]=(struct dat *)new(struct dat) //тут может быть ошибка
{т.е. выделяешь память под date[ i ]. Если не будешь писать конструктор и тебе комфортнее, можешь выделять память маллоком. Но лучше new}
а чтобы инициализировать char *dat4;, просто напиши конструктор
или не пиши конструктор, и если будешь что нибудь присваивать, делай это типа так
free(date[ i ]->dat4); date[ i ]->dat4=strdup(твоя строка) // strdup выделяет память
вобщем это зависит от того, какие операции планируешь делать с этим атрибутом
Я бы так сделал как нибудь
Это что такое?
struct dat {
int dat1;
int dat2;
int dat3;
char *dat4;
double dat5;
dat
{
// конструктор
dat4=malloc(сколько надо байт);
}
};
struct dat ** date;
// ссылка на ссылки на объекты struct dat}
date = (struct dat **)mallocсколько хочу)* (sizeof(struct dat*;
for(i:=0 i<сколько хочу; i++) date[ i ]=(struct dat *)new(struct dat) //тут может быть ошибка
// т.е. выделяешь память под date[ i ], при этом конструктор сразу выделяет память под dat4
free(date[ какой тебе нужен ]->dat4); date[ какой тебе нужен ]->dat4=strdup(что хочешь присвоить)
// strdup выделяет память
Я бы так сделал как нибудь.
И ещё я, хотя и gcc компилирую, пишу на сях и конструкторов не пишу
А вообще - спасибо!
Хорошо что я не линуксоид
Хорошо что я не линуксоидЩа тебя съедят
new это не C. И линукс здесь не причем.
а malloc кастить-то зачем ? типа это нехорошо считается
Поясни. Прокомментируй.
чтоб варнинга не было
и не будет варнингов
А если вдруг нужно будет скомпилировать код как C++, явное приведение позволяет избежать варнинга.
если надо компилировать как C++, то да, касты нужны. однако оставаясь в рамках языка C считается, что касты скорее вредны, чем полезны.
На Це тоже нужен каст, если -Wчего-то-там-точно не помню.
что-то я не понял.... это стандартом утверждается, что void* преобразовывается без кастов. Какой еще -Wbla-bla ?
Хмм. Я не смог найти этот -W. Но я помню, что когда-то я добавлял касты для того, что бы не было warningов.
явное приведение позволяет избежать варнингаВ с++ отсутствие каста - это не warning, это error.
test.cpp:5: ANSI C++ forbids implicit conversion from `void *' in assignment
Вообще нет никакой _объективной_ причины разрешать кастить void* в любой указатель. Когда придумывали Си, подозреваю, что такое решение было принято _именно_ из-за этого убожества с malloc-ом.
С с шаблонами бывает? т.е. без объектов, но с шаблонами?
зависит от параметров компиляции, иногда настроек операционки
для защиты от бесконечной утечки памяти область данных ограничена
еще при бесконечной рекурсии сильно утекает процессорное время так что лучше не ждать, пока заполнятся гига 3 оперативы, а пресечь чуть пораньше
Вопрос: а как я в своё время умудрялся делать программы на фортране (как под Windows, так и под Linux которые использовали порядка 500 мегабайт памяти, причём всё из стека? Динамического выделения памяти я не использовал, параметров компиляторам никаких специальных не передавал...
при бесконечной утечки памяти процессорного времени утекает ещё больше (выделять память на стеке проще, чем в куче
так что, казалось бы, зачем ждать, пока заполнятся почти 3 гига?
а на самом деле всё просто - на Си и подобных языках глубокая рекурсия не принята, а утечки памяти - приняты
Вариант 2: ты (или фортрановский рантайм) увеличил ограничения
параметров компиляторам никаких специальных не передавалНу значит фортран сам за тебя уносил большие массивы со стека. Они же известной длины были...
а на самом деле всё простоКо всему прочему, многотредовой программе нужно _много_ стеков, причем их (в отличие от однотредового случая) нельзя наращивать "по необходимости"... Поэтому должно быть некоторое разумное и зафиксированное ограничение.
Да, в таких программах стека ещё меньше. Ненавижу.
Кстати, мы тут на работе недавно заметили. В Яве такой проблемы быть _не должно_. В ней нельзя сослаться на ячейку в стеке. То есть в Яве указатели в heap бывают, а в стек - нет, и следовательно vm может переносить стек треда куда угодно, если это нужно для того, чтобы его удлинить. Удивительно, но несмотря на это, в Яве такие же ограниченные стеки у тредов, странно...
Вот для функционального программирования рекурсия является основным механизмом,
а всё равно в тех рантаймах, что я смотрел, используют системный стек
А разве Явовские треды не отображаются в нативные треды для данной платформы?
А ты думаешь почему в Java нет передачи параметров по ссылке.
Кстати, мы тут на работе недавно заметили. В Яве такой проблемы быть _не должно_. В ней нельзя сослаться на ячейку в стеке.
Даже интересно, ну и почему?
Ява - это хуйня.Щас Глеб тебя ознакомит с правилами раздела!
Вот для функционального программирования рекурсия является основным механизмомНу хвостовую рекурсию компиляторы берут, да и вообще, в функциональном языке все данные в heap-е, на стеке только несколько ссылок хранить надо. Ты столько локальных переменных не поназаводишь, чтобы стек кончился
map на длинный список не пройдет.
А разве Явовские треды не отображаются в нативные треды для данной платформы?В имеющихся jvm или в принципе? Это же технический вопрос, а они имеют склонность быть разрешимыми. Можно в конце концов сигнал перехватывать при stack-overflow и разруливать там как то...
Даже интересно, ну и почему?Для этого нужно, чтобы JVM поддерживала указатели на данные в стеке, хотя бы с ограничениями как в .NET
pthread_attr_setstacksize ? или я не понял о чем речь ?
Это и есть "почему"? Ну должна поддерживать, ну и что дальше?
pthread_attr_setstacksize ?Ну если в программу много тредов, то просто виртуальные адреса кончатся и все. И еще раз повторяю, если тредов несколько, то размер стека надо выбирать _заранее_, а если тред один, то можно наращивать по необходимости, основное отличие в этом.
PS куда-то разговор зашел..
Почему нельзя размер каждого стека наращивать по необходимости?
Это вызвано какими-то высшыми причинами?
или это связано с проблемами конкретной реализации?
Потому что адресное пространство, в которое ты хочешь нарастить стек, может быть уже занятым данными другого треда. По моему так.
Это и есть "почему"? Ну должна поддерживать, ну и что дальше?В смысле? Ну да, для реализации параметров по ссылке в JVM нужны указатели. Там их нет, вот и передачи по ссылке тоже. Я думаю, что Sun изначально не хотела сложную VM, чотбы не было проблем с реализациями на других платформах. На "чистоте языка" это ни как не сказывается. Есть фича, которой редко пользуются, ни кому не мешает. Но когда очень надо, то пожалуйста.
Сейчас же и для стека и для данных используются разные сегменты памяти.
Мне в целом не нравится позиция Sun в отношении к языку Java. Хотите язык, чтобы писать j2ee пиложения, ок, Java 5.0 вполне годится. Но ведь Java платформа - эта платформа одного языка. А на роль универсального языка Java не дотягивает. Вот лично я прогаю всякие алгоритмы под Java и постоянно сталкиваюсь в ограничениями (надуманными во многом). Часто я хочу выделить общие куски кода в один метод, но каждый раз приходится изворачиваться, если это код должен менять значения нескольких переменных.
PS: в стековом сегменте они и не могут находиться по другому. Если же поместить их в сегмент данных - то тогда уже нельзя увеличить размер стека так как в виртуальном адресном пространстве необходимые адреса уже могут быть занятыми.
PPS: сегментная модель памяти не всегда может быть доступной.
Такая фигня только раньше была - когда не было виртуальной памяти."В огороде бузина, а в Киеве дядька"
Сейчас же и для стека и для данных используются разные сегменты памяти.
Проблема не в самой памяти (она все равно страничная и виртуальная а в адресации этой памяти.
Адресация-то у нас одна и линейная.
Но в Java-е и .Net-е можно было попытаться избежать этой проблемы - нативных адресов у них все равно нет.
вроде в винде есть ограничение (2048) на кол-во тредов в оном процессе, хотя может и гоню
тогда стеки могут быть довольно большими
а в 64bit архитектурах такой проблемы наверно вообще нет.
Сейчас же и для стека и для данных используются разные сегменты памяти.Стековый сегмент остался в прошлом веке, он использовался как раз _до_ появления виртуальной памяти. Сейчас все виртуальное адресное пространство однородное, адресуется 32-х битным адресом, который является самодостаточным (то есть никакого указания сегмента не требуется). Понятие "сегмента" в современном процессоре имеет отношение только к тому, в каком виде на виртуальные страницы накладываются ограничения read/write. Короче - минус балл.
У кого 32, а у кого и все 64
mov [ds:ax], ...
сейчас используется только для старта ОС.
> mov [ds:ax], ...
> сейчас используется только для старта ОС.
у x86_64 в long mode юзаются FS: и GS:
адресуется 32-х битным адресом, который является самодостаточным (то есть никакого указания сегмента не требуется)Хуй там. В i386 никуда сегментация не делась.
Просто во всех популярных ОС дескрипторы сегментов настраиваются "вырожденным" образом. Впрочем, не всегда. Например, в винде FS указывает на блок параметров процесса (или что-то типа того, лень вспоминать).
у x86_64 в long mode юзаются FS: и GS:Согласен, 64 для меня пока темный лес...
Только у этих двух сегментов база рассматривается в качестве смещения,
поэтому обобщение до конкретных команд не срабатывает.
проверку на арифметическое переполнение не забудь
Оставить комментарий
bvasilik
Подскажите, плз...Есть некая структура.
struct dat {
int dat1;
int dat2;
int dat3;
char *dat4;
double dat5;
};
Во-первых, когда я пытаюсь сделать
struct out date[number];
При очень больших number прога вываливается.
Во-вторых, для *dat4 как-то надо выделить место, а как?
Заранее спасибо!