PIC(XC16)の動的メモリ確保の話

〔PICの動かせ方入門に戻る〕


最近知った話、って言うかぁUSBホスト機能をいじっていた時気付いた話。
XC16コンパイラには動的にメモリを確保(dynamic memory allocation)するメモリ管理が出来る様です。
これが出来るとすご〜ぉく重宝します。
例えば、ある関数でデータを入れてソート等を行う場合、入力されるデータ長は非固定の場合ですとぉ、
関数内で想定されるMAX長のバッファを用意する必要が有りますがぁ、この機能が使えれば関数内は
その都度データ長に応じてバッファサイズを可変させてメモリを確保すれば良く、メモリが効率的に
利用出来ます。

ヒープ領域

プログラムが自由に読書き出来る領域(SRAM)で使用するメモリのサイズをリンカに登録しないとダメです
リンカはスタックの直下に指定したサイズ分のヒープを割り当てます。
利用可能なメモリが足りない場合は、エラーが報告されますので、それなりのサイズを指定しましょう。

@ MPLAB X IDEのツールバーから[File]→[Project Properties(xxx)]を順番にクリックします。
  プロジェクトプロパティ画面(下記図)が表示されます。

ヒープ領域の割り当て画面
A 表示された画面左側の[Categories:]から"xc16-ld"の項目をクリックします。
B 表示された画面右側で、[Option categories:]は"General"ですね。
C 画面右下側で、[Heap size]に最大確保するであろうサイズをバイト単位で入力します。

尚、この操作は"MPLAB X v4.10"と"XC16 v1.30"での方法で他の場合は操作方法が異なるかもね。

メモリの割付けと解放を行う関数説明

先ず、使用する場合は#include <stdlib.h> が必要です。
(XC16の場合は"stdio.h"でなく"stdlib.h"の様です間違わない様に)

ptr = malloc(size)
指定したサイズ分のメモリの割り付けを要求します。

 unsigned int size : 割り付けたいメモリの大きさを指定します
 char*    ptr : 成功した場合は割り付けられたメモリへのポインタを返します
          メモリが無い場合は0を返します。

free(ptr)
割り付けられているメモリを解放します。

 char* ptr : 解放するメモリへのポインタを指定します

 例)
    char *ptr ;

    ptr = malloc(12) ;
    memcpy(ptr,"memory test",1) ;
    free(ptr) ;
p = realloc(ptr,size)
既に割り付けられているメモリのサイズを変更します。

 unsigned int size : 変更したいメモリの大きさ(増減)を新たに指定します
 char*    ptr : 既に割り付けられているメモリへのポインタを指定します
 char*    p  : 成功した場合は新たに割り付けられたメモリへのポインタを返します
           メモリが無い場合は0を返します。
           p=ptrとは限らない、新たなアドレスの場所に割り付けられる場合が有る為です。

ptr = calloc(bnum,bsize)
ブロック単位でメモリの割り付けを要求します。
構造体を割り付けるのに便利でしょう。

 unsigned int bnum: 割り付けるブロックの数を指定します
 unsigned int bsize : 1ブロック当りのサイズを指定します
 char*    ptr : 成功した場合は割り付けられたメモリへのポインタを返します
           メモリが無い場合は0を返します。
 例)
    #define ADDRESSBOOK_SU 10

    struct {
        char name[20] ;
        char tel[12] ;
        char adrs[50] ;
    } c ;
    char *p , *ptr ;
    int i ;

    p = ptr = calloc(ADDRESSBOOK_SU,sizeof(c)) ;
    for (i=0 ; i < ADDRESSBOOK_SU ; i++) {
         // 以下の処理例はマイコン的でない記述方法です m(_ _)m
         printf("Name : ") ;
         scanf("%s",p->name) ;
         printf("TEL : ") ;
         scanf("%s",p->tel) ;
         printf("Address : ") ;
         scanf("%s",p->adrs) ;
         p++ ;
    }


《その他》

通常の静的メモリでコンパイルして残りのデータメモリをヒープ領域とすれば良さげかも?




【きむ茶工房ガレージハウス】
Copyright (C) 2006-2019 Shigehiro Kimura All Rights Reserved.