0

I have a function f(q15_t *x, inst *z) it have an input x and an instance z:

typedef struct {
q15_t * pbuff;
}inst;

inst z;

I want an initializer function able to allocate memory space and place it's address to z.pbuff, like (my effort):

instance_initiator(inst *instance,uint16_t buffSize)
{
q15_t a[buffSize];
instance->pbuff=a;
}

I'm searching for correct way to do this, since I think after initiator function finished the buffer allocated spaces will vanishes and it seems we need global variable and this can't happen may be by making a static? I hope to being able to do this.

Note the initialization will run once and the function will be called many times.

As Vlad from Moscow told malloc is good but I feel fear if that is slowing algorithm? Maybe one way is to set the size of static array a by macro.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
mohammadsdtmnd
  • 330
  • 1
  • 11
  • You can create a memory pool as shown [here](https://stackoverflow.com/a/70667901/584518) and optionally pass the allocation method along. A bit of it depends on if these structs are opaque or if their definitions are public to the whole project. – Lundin Mar 08 '22 at 11:02
  • 1
    Regarding the use of malloc in microcontroller systems, check out this: https://electronics.stackexchange.com/a/171581/6102 Basically using malloc is completely senseless and just creates a lot of bloat for no good reason. – Lundin Mar 08 '22 at 11:16
  • If the `inst` is created by a function and is not used after the function returns, then replacing `inst` with a variable length array may be an option. (I would have suggested replacing the `pbuff` member of `inst` with a flexible array member, but that requires `inst` to have another member before the flexible array member. Perhaps the other member could hold the length of the array though. This would also require a pointer to `inst` to be passed to function `f` rather than a copy of `inst`.) – Ian Abbott Mar 08 '22 at 11:20
  • @IanAbbott What you mean inst not used afterward? every `f` function call also pull `inst` inside. the size of structures and their buffers are constand, at least at this stage of program development. – mohammadsdtmnd Mar 08 '22 at 11:25
  • I mean if `inst` is created on the stack as a flexible array, then it could not be used after the function that created it on the stack returns. That is also why your `instance_initiator` function above cannot work, because it is using variable `a` after the function returns. – Ian Abbott Mar 08 '22 at 11:28
  • @IanAbbott How is that implementation? – mohammadsdtmnd Mar 08 '22 at 11:34
  • Well to create a variable length array on the stack, you would just declare it with its length set by a non-constant expression. To create a struct variable on the stack with a flexible array member is a bit harder. You either need to embed it in a union that provides enough space for the struct and its flexible array member, or you need an initializer that initializes the last element (that is slower than using a union if you do not want to initialize the array contents). – Ian Abbott Mar 08 '22 at 14:56
  • @IanAbbott Could I know how is these two implementation, though Lunden told stack usage for large array is vad idea. THX – mohammadsdtmnd Mar 08 '22 at 15:44
  • 1
    the usual way to handle 'mallac' and friends, to avoid delays in the execution of a program, is to do all the 'malloc'ing during initialization and all the 'free'ing during program shutdown. That way the main loop of the program is not delayed. – user3629249 Mar 09 '22 at 02:52
  • 1
    @user3629249 Again, this isn't for a PC, hence the embedded and stm32 tags. Can everyone please stop making PC programmer know-it-all comments below a topic they have no knowledge about? – Lundin Mar 09 '22 at 07:40
  • 1
    I have designed/written hundreds of programs (some with over 100k lines) on small microprocessors if you do not want to listen to the wisdom of experience, that is up to you. However, don't be bad mouthing those with the first hand experience. – user3629249 Mar 09 '22 at 08:56
  • @user3629249 If you say so. Do all of those hundreds of small microprocessors have program shutdown or just a selected few? – Lundin Mar 09 '22 at 15:51
  • @Lundin Do you mean this procedure is helpfull for shutdown program? – mohammadsdtmnd Mar 10 '22 at 05:27

2 Answers2

0

I've found a solution but I don't know if ever anyone named this solution or not:

#define SIZEOFBUF 500

typedef struct {
q15_t * pbuff;
}inst;

typedef struct {
q15_t buff[SIZEOFBUF];
}instScratch;

inst_initiator(instScratch* scr,inst* z)
{
    inst->pbuff =instScratch->buff
}

void main(void)
{
    static instScratch scr;
    inst z;
    inst_initiator(&inst,&scr);

loop
{
f(x, &z);
}
}

This solution has been possible since static variable's size assumed to be known in compile time, if that wasn't, and the size of buffer determines only in the run time, EZ solution is to use malloc but (as Lundin told) dynamic allocation is forbidden for embedded and you could use Lundin's static memory pool's solution.

mohammadsdtmnd
  • 330
  • 1
  • 11
  • 1
    This is just declaring a plain array on the stack... which is a very bad idea. What exactly is the problem that you are trying to solve? – Lundin Mar 08 '22 at 12:18
  • @Lundin Why is bad and what is it's difference from stack pool? I'm created stack pool in this way, why this is unacceptable? You told it's better to used stack, doesn't it? then it's stack usage?! – mohammadsdtmnd Mar 08 '22 at 12:20
  • 1
    Because you are coding on a microcontroller with limited stack space. – Lundin Mar 08 '22 at 12:23
  • In case your beginner classes failed to mention it, you should probably start by studying this: [What resides in the different memory types of a microcontroller?](https://electronics.stackexchange.com/a/237759/6102) – Lundin Mar 08 '22 at 12:25
  • @Lundin That was epic, thanks, you mean declaring `instScratch scr;` must be static? To being placed on the .data and .bss? – mohammadsdtmnd Mar 08 '22 at 12:51
  • Yes indeed, or otherwise you grab a very large chunk of your stack and risk stack overflows. – Lundin Mar 08 '22 at 12:55
  • @Lundin As a matter of fact `god belss you` – mohammadsdtmnd Mar 08 '22 at 12:56
  • @Lundin But the question rized for me: you've told not use auto since we have limited stack, but placing `a` on .bss will not increase stack but increase .bss and again it reduces stack space, then whats point? – mohammadsdtmnd Mar 08 '22 at 13:52
  • 2
    The point is that when the stack is full you get a mysterious run-time crash. When .bss is full you get a link-time error. Plus any memory corruption bugs on the stack might damage other things there. It's good practice to never declare large arrays on the stack, in particularly not communication buffers and similar. – Lundin Mar 08 '22 at 14:49
0

Allocate using malloc(). Test for success.

// Return error flag
bool instance_initiator(inst *instance, uint16_t buffSize) {
  if (instance == NULL) {
    return true;
  }
  instance->pbuff = malloc(sizeof instance->pbuff[0] * buffSize);
  return instance->pbuff == NULL && buffSize == 0;
}

malloc is good but I feel fear if that is slowing algorithm?

Have no fear. Review Is premature optimization really the root of all evil?.

If you still feel malloc() is slow, post code that demonstrates that.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 1
    malloc cannot be used in embedded systems. The main reason isn't execution speed or even the huge waste of space involved in allocating room for a heap, but that malloc is completely senseless to use in a fully deterministic system. – Lundin Mar 09 '22 at 07:38
  • @Lundin Respectfully disagree. You comment certainly applies in many, if not most, cases today. Yet as embedded systems advance, they become less deterministic and more complex. IOT is fairly dynamic. – chux - Reinstate Monica Mar 09 '22 at 15:06
  • 1
    It applies to STM32 for sure. – Lundin Mar 09 '22 at 15:46