Көрсеткіштерде malloc көмегімен динамикалық жадты бөлу қажет пе?

Менде malloc() функциясын C функциясында толық түсіну қиын болса, дәлірек оны пайдалану қажет болғанда.

Мен жаһандық құрылымға көрсеткішті жариялағанда,

struct Position* currentPositionPtr;

malloc арқылы оны инициализациялау үшін динамикалық жадты тағайындау керек пе? Немесе құрылымның көрсеткішін кейінірек қажет болған кезде оған сілтеме жасау жақсы тәжірибе.

currentPositionPtr = getPosition();

онда getPosition() сілтегішті «struct Position» -қа қайтарады.

2
malloc() әдетте бағдарламаны іске қосқанша қажет нәрсе не қанша нәрсені білмесеңіз, бөлу).
қосылды автор jxh, көзі
@ H2CO3: Қайтарылатын функцияның қайтарылымы болсам, есімде өтетін қоңырау шалушының әдісі мен түрі ашық емес болса, басқа функциялармен пайдаланылатын жады құру үшін айқын «жасау» функциясын ұнатамын.
қосылды автор jxh, көзі
@ H2CO3: Қайтарылатын функцияның қайтарылымы болсам, есімде өтетін қоңырау шалушының әдісі мен түрі ашық емес болса, басқа функциялармен пайдаланылатын жады құру үшін айқын «жасау» функциясын ұнатамын.
қосылды автор jxh, көзі
@ H2CO3: Немесе қатені іздеңіз. Бірақ сіздің маршрутизаторыңыз қазірдің өзінде құлап қалған болса, онда бәрі сізде қазірдің өзінде белгіленген. :-)
қосылды автор jxh, көзі
@ H2CO3: Мен үшін көрсеткішті массивке сипаттау үшін шексіз VLA ғана пайдаланамын. Манипуляция үшін уақытша жады үшін, мен көп уақытты жұмыс істейтініне сенімдімін және ол үлкенірек болса, динамикалық түрде бөлінетін тұрақты ұзындық аралықты пайдаланғым келеді. Бұл тек қана стек шығаруды болдырмау үшін ғана.
қосылды автор jxh, көзі
Бұл шын мәнінде динамикалық жад бөлуді/қашан қолдануды сұрайды? malloc дегеніміз не екенін түсінген сияқты. Сіз бұл мақаланы оқығыңыз келуі мүмкін: en.wikipedia.org/wiki/C_dynamic_memory_allocation
қосылды автор lurker, көзі
@jxh (және сізге 100000000 элементтердің уақытша буферлері қажет болса, онда кодты қайта жасау жақсы болар еді, мен қосу керек).
қосылды автор user529758, көзі
@jxh C стандартты кітапханасы да бар, және сіз дұрыс боласыз. Мен құрылтайшыларды да жазады, олар мультипликациялық көрсеткішті қайтарады, бұл жақсы және оқылатын болып табылады. (Бірақ контрастындар да бар ...)
қосылды автор user529758, көзі
@jxh C стандартты кітапханасы да бар, және сіз дұрыс боласыз. Мен құрылтайшыларды да жазады, олар мультипликациялық көрсеткішті қайтарады, бұл жақсы және оқылатын болып табылады. (Бірақ контрастындар да бар ...)
қосылды автор user529758, көзі
@jxh ... aaaaaand функциясы аман қалу үшін массив/құрылым қажет. 2013 жылы, динамикалық орналастыру үшін нақты қажеті жоқ болса, автоматты түрде сақтау мерзімі бар VLA-ді пайдалану үшін емес себеп жоқ.
қосылды автор user529758, көзі
Мен мұны да үміттенемін, әлдеқайда жақсы атауға өзгерткенін түсіндім.
қосылды автор noe, көзі

8 жауаптар

getPosition() дегеніміз не?

struct Position дегенге жарамды көрсеткішті қайтарса, онда, әрине, struct үшін екі есе жады бөлудің қажеті жоқ. функциясы емес келесідей көрінеді:

struct Position *getPosition()
{
    struct Position p = { x, y };
    return &p;
}

себебі бұл белгісіз мінез-құлықты көрсететін болады (көрсеткішті автоматты түрде автоматты түрде блоктық аумаққа қайтару арқылы). Әдетте, орнына қазірдің өзінде malloc() айқындаған көрсеткішті қайтаруыңыз керек:

struct Position *getPosition()
{
    struct Position *p = malloc(sizeof(*p));
    p->x = 42;
    p->y = 1337;
    return p;
}

Содан кейін қайтадан malloc() қосымша қоңырауына қажеті жоқ.

Егер, алайда, бөлу үшін жауапты функция емес болса, онда жақсы ... бұл қоңырау шалушы:

void getPosition(struct Position *p)
{
    p->x = 42;
    p->y = 1337;
}

Және осы соңғы жағдайда сіз оны келесідей деп айтуға болады:

struct Position *p = malloc(sizeof(*p));
getPosition(p);

Егер сізге функцияны қайтару үшін құрылым қажет болса, немесе

struct Position p;
getPosition(&p);

егер болмасаңыз.

8
қосылды
getPosition жаһандық құрылымдық позицияға жарамды көрсеткішті қайтарады (ол бұрын кейбір стандартты мәндермен инициализацияланған). Сондықтан, сіз айтқан сияқты сақтауды екі есе бөлуім керек болмас еді. Рахмет!
қосылды автор noe, көзі

Әдетте, malloc келесі жағдайларда қолданылады:

  1. жадты динамикалық түрде бөлуді қаласаңыз: Басқа сөзбен айтқанда, қанша жады қажет екенін білмесеңіз. Немесе қажет болған кезде оны білмей жатқанда.
  2. өте көп мөлшерде жад бөлу керек болғанда: Қабырға өте үлкен болады, бірақ стек әлдеқайда шектелген. Қаптамада өте үлкен нәрсе бөліп, стака толып кетуіне әкелуі мүмкін ( hey, бұл сайттың атауы ). Әрине, мұндай өлшемдер нақты жүзеге асады, демек, «өте үлкен» деген өте субъективті фраза.
  3. Бөлінген жадты сырттан қолжетімді болғыңыз келгенде: Егер сіздің бағдарламаңыздың басқа жіптері бір жадқа кіруді қажет етсе, оны бір ағынның стекке бөлу қажет болса, бұл жіп аударылған кезде қайта жазылуы мүмкін, сонда қалғандардың бәрі бүлінген жадыға қарайтын болады.
  4. Мүмкін, тағы бірнеше басқа жағдайлар.
1
қосылды

malloc (or another memory-allocating function) is needed whenever you need the system to give memory to you.

Сонымен, сіз жасай аласыз

struct Position* currentPositionPtr;

Сізге malloc() деген қоңырау керек болады:

currentPositionPtr = malloc(sizeof(struct Position));

немесе әлдеқашан бөлінген жады блогының мекенжайына көрсеткішті тағайындау керек:

struct Position globalPos;

void func(void) {
    struct Position pos;
    struct Position* currentPositionPtr = &pos; //ok
    struct Position* globalPosPtr = &globalPos; //also ok
    ...
}

себебі сіз жасай отырып, құрылымға арналған кеңістікті сақтамай, көрсеткішті жариялап отырсыз.

Дегенмен, сіздің көрсеткішіңіз global болса, оны стекке бөлінген жадқа тағайындау ықтимал қауіпті. Төмендегілерді қарастырайық:

struct Position *globalPosPtr = NULL;

void foo(void) {
    struct Position pos;
    globalPosPtr = &pos;
    //can dereference globalPosPtr with no problems here
    ...
}

void bar(void) {
    foo();
    //globalPosPtr is invalid here
    ...
}

Көрсеткішті қайтаратын басқа функция туралы сұрағыңызға келетін болсаңыз:

getPosition() will need to use malloc or some other memory-allocating function itself. So doing that is perfectly fine, and can make sense if you generally want to initialize values in the struct to some values. However, remember that, even if you called malloc inside some other function, you will need to free the memory when you are done using it to prevent memory leaks.

Тақырыптағы сұраққа жауап беру үшін, көрсеткіш ретінде қандай да бір нәрсені жариялаған кезде оны пайдалану керек пе, оны көрсету керек. Егер сіз жаңа нәрсені көрсетгіңіз келсе, оны malloc() немесе тиісті функциясымен динамикалық түрде бөлу керек.

1
қосылды
H2CO3-дің түсініктемесі мынада, міне, мағынасы бар: бұл кодты ұнатпаймын: «Иә, сіз істеп жатқан кезде struct позициясы * currentPositionPtr; қолданар алдында malloc() көрсеткіш «себебі бұл сөзі дұрыс емес. Көрсеткішті қолдану malloc() пайдалануды талап етпейді, ол жай стекке жергілікті айнымалы адреске орнатылуы мүмкін.
қосылды автор Mike, көзі
Менің жауапымды әскери қызметкерге өте қарапайым етіп қоюға тырысамын деп ойлаймын, мен өте күшейтілген. Мен оны өңдеймін.
қосылды автор Eric Finn, көзі
@ H2CO3 Бұл жақсы ма?
қосылды автор Eric Finn, көзі
@Mike дәл. Сол себепті « malloc сізге қажет жады қажет болғанда қажет» деген сөз де жалған.
қосылды автор user529758, көзі
@EricFinn Иә, мінсіз.
қосылды автор user529758, көзі

malloc (or another memory-allocating function) is needed whenever you need the system to give memory to you.

Сонымен, сіз жасай аласыз

struct Position* currentPositionPtr;

Сізге malloc() деген қоңырау керек болады:

currentPositionPtr = malloc(sizeof(struct Position));

немесе әлдеқашан бөлінген жады блогының мекенжайына көрсеткішті тағайындау керек:

struct Position globalPos;

void func(void) {
    struct Position pos;
    struct Position* currentPositionPtr = &pos; //ok
    struct Position* globalPosPtr = &globalPos; //also ok
    ...
}

себебі сіз жасай отырып, құрылымға арналған орынды сақтамай, көрсеткішті жариялап отырсыз.

Дегенмен, сіздің көрсеткішіңіз global болса, оны стекке бөлінген жадқа тағайындау ықтимал қауіпті. Төмендегілерді қарастырайық:

struct Position *globalPosPtr = NULL;

void foo(void) {
    struct Position pos;
    globalPosPtr = &pos;
    //can dereference globalPosPtr with no problems here
    ...
}

void bar(void) {
    foo();
    //globalPosPtr is invalid here
    ...
}

Көрсеткішті қайтаратын басқа функция туралы сұрағыңызға келетін болсаңыз:

getPosition() will need to use malloc or some other memory-allocating function itself. So doing that is perfectly fine, and can make sense if you generally want to initialize values in the struct to some values. However, remember that, even if you called malloc inside some other function, you will need to free the memory when you are done using it to prevent memory leaks.

Тақырыптағы сұраққа жауап беру үшін, көрсеткіш ретінде қандай да бір нәрсені жариялаған кезде оны пайдалану керек пе, оны көрсету керек. Егер сіз жаңа нәрсені көрсетгіңіз келсе, оны malloc() немесе тиісті функциясымен динамикалық түрде бөлу керек.

1
қосылды
H2CO3-дің түсініктемесі мынада, міне, мағынасы бар: бұл кодты ұнатпаймын: «Иә, сіз істеп жатқан кезде struct позициясы * currentPositionPtr; қолданар алдында malloc() көрсеткіш «себебі бұл сөзі дұрыс емес. Көрсеткішті қолдану malloc() пайдалануды талап етпейді, ол жай стекке жергілікті айнымалы адреске орнатылуы мүмкін.
қосылды автор Mike, көзі
@ H2CO3 Бұл жақсы ма?
қосылды автор Eric Finn, көзі
Менің жауапымды әскери қызметкерге өте қарапайым етіп қоюға тырысамын деп ойлаймын, мен өте күшейтілген. Мен оны өңдеймін.
қосылды автор Eric Finn, көзі
@Mike дәл. Сол себепті « malloc сізге қажет жады қажет болғанда қажет» деген сөз де жалған.
қосылды автор user529758, көзі
@EricFinn Иә, мінсіз.
қосылды автор user529758, көзі

Менің ойымша, malloc қалай жұмыс істейтінін білесіз, бірақ мен сіздің сұрағыңызға жауап беруге тырысамын.

Сіз қашан мультипликаторы болсаңыз, оны басқаруға (немесе оны босатуға) арналған көрсеткішті ұстаңыз. Malloc-тің дамуы - ол динамикалық болып табылады. Массивтерді жариялаудың орнына, сіз malloc'd құрылымдарының байланыстырылған тізімін жариялай аласыз және оларды бақылау үшін көрсеткішті қолдануға болады. Осылайша, массивтен шығып кету сияқты проблемаға ешқашан араласпаңыз. Оның орнына, сіз жай ғана көбірек орынды сұрап, қажет болғанда оны босатыңыз.

0
қосылды

Менің ойымша, malloc қалай жұмыс істейтінін білесіз, бірақ мен сіздің сұрағыңызға жауап беруге тырысамын.

Сіз қашан мультипликаторы болсаңыз, оны басқаруға (немесе оны босатуға) арналған көрсеткішті ұстаңыз. Malloc-тің дамуы - ол динамикалық болып табылады. Массивтерді жариялаудың орнына, сіз malloc'd құрылымдарының байланыстырылған тізімін жариялай аласыз және оларды бақылау үшін көрсеткішті қолдануға болады. Осылайша, массивтен шығып кету сияқты проблемаға ешқашан араласпаңыз. Оның орнына, сіз жай ғана көбірек орынды сұрап, қажет болғанда оны босатыңыз.

0
қосылды

егер сіз белгілі бір өлшеммен құрылымды қолдансаңыз, еске салу үшін malloc пайдалануыңыз керек, себебі жады әр түрлі құрылымдық позицияға дейін өзгермейді,

егер құрылымдық позицияда кейбір пайдаланушы кірісіне байланысты белгісіз мөлшері бар көрсеткіш болса, онда сізге қажетті жад блок мөлшерін бөлу үшін malloc пайдалануға болады.

сондай-ақ егер сіз struct орналасу жиымын бөліп алсаңыз

currentPositionPtr = malloc(sizeof(struct Position)*neededSize);

Сіз жасағаннан кейін, жадты өшіруіңіз керек

free (currentPositionPtr)
0
қосылды

Түсінудің қарапайым нәрселері бар:

  1. malloc() жай еске жадтан және пайдаланушы процесінің жауапкершілігін ТЕГІН жүйелік қоңырауға қоңырау шалу арқылы бұл жадты ТЕГІН етіп қайтарады.

  2. Кодтау уақытында белгілі бір жад көлемімен айналысуға тура келетінін білесіз: struct, массив, содан кейін жергілікті айнымалы және Жаһандық айнымалы мәндермен процестің есте сақтау талабын қанағаттандыра аласыз.

Сұрауыңыздан malloc-пен күресуге тура келгенде және нəтиже көрсеткіштері болған кезде шатастыруға болады.

  1. You need a pointer to hold the address of the memory allocated by malloc system call.
  2. The pointer not necessarily point to the memory allocated by malloc,it can be any valid memory like:

     int a =2;
     int *ptr; 
     ptr = &a;
    

Мәселен, мұнда, ptr нүктеге malloc бөлінбеген EMO орындары.

Керісінше, сіз мұны істей аласыз

   int *ptr;  
   ptr = (int*)malloc(sizeof(int));

Сіздің жағдайыңызда currentPositionPtr көрсеткішінің стильге көрсетілуі жадыны/жергілікті айнымалы адрестің мекен-жайын көрсете алады, сонда жады мекен-жайы осы көрсеткіштің қол жетімділігінде жарамды болады.

Бұл нәрселерді жеңілдетеді деп сенемін.

0
қосылды
Сіз дәл осында, сіздің жағдайда currentPositionPtr көрсеткіші жаһандық құрылымға нұсқайды, бұл көрсеткіш жаһандық айнымалы мәнге ие болғанға дейін жарамды екенін білдіреді. Бірақ бәрібір жаһандық айнымалыға тікелей қол жеткізе аласыз, неге ол көрсеткіш арқылы қолжетімділік қажет?
қосылды автор uni, көзі
Okay .... Cheers !! Жалғастырыңыз.
қосылды автор uni, көзі
currentPositionPtr параметрі struct Position пішімінің дұрыс баптандырылған жаһандық айнымалы мәнін көрсетеді. Жаһандық айнымалы болып табылатындығы жадтың мекен-жайы бағдарламаның бүкіл орындалуында жарамды екеніне кепілдік береді немесе мұнда қателесем бе? Қалай болса да, бірнеше нәрсені түсіндірген түсініктеме үшін рақмет!
қосылды автор noe, көзі
Бағдарлама STM32 микроконтроллерінде жұмыс істеп жатыр, мен құрылымның көрсеткішін бүкіл құрылымды құндылыққа қарағанда әлдеқайда тиімді деп ойлаймын. Бірақ, мен оған ешқандай функциясыз тікелей қол жеткізе алатын болсам, ол әлі де ең жылдам болады. Осылайша, бұл жағдайда оған тікелей кіруге мағыналы болады, бірақ мен жалпы malloc-мен шатастырылдым, бұл жай ғана мысал.
қосылды автор noe, көзі