Products > Programming

malloc to struct pointer = hard fault. What am I doing wrong?

(1/3) > >>

DavidAlfa:
I'm working on dinamically allocating the screens in the stm32 fw, so I can reduce the ram footprint.
A rough description is: Theres a "widget" struct. It holds some data like position and other things, and also a pointer to the content.
The content is like a "sub-widget", can be a button, editable, display...
So what I'm doing is to first allocate the widget, then allocate the sub-widget depending on the type.
However when accessing the subwidget, it causes hard fault with the combo type.
This worked perfectly fine before, using static allocations. It started to happen after using malloc. sizeof reports the correct sizes. mallinfo also reports the correct size being allocated (+8 bytes per malloc).
It's not running out of  heap or stack, it happens with the very first allocation, it's just with the combo type. I can allocate anything else correctly.


--- Code: ---struct selectable_widget_t {
  widgetStateType state;
  widgetStateType previous_state;
  uint8_t tab;
  int (*processInput)(widget_t*, RE_Rotation_t, RE_State_t *);
  int (*longPressAction)(widget_t*);
};

--- End code ---

--- Code: ---struct comboBox_widget_t {                                           //<-- void *content addresses this
  uint8_t currentScroll;
  const uint8_t* font;
  comboBox_item_t *first;
  comboBox_item_t *currentItem;
  selectable_widget_t selectable;
};

--- End code ---

--- Code: ---struct widget_t
{
  widgetType type;
  widgetRefreshType refresh;
  widgetFrameType frameType;
  uint8_t posX;
  uint8_t posY;
  uint8_t width;
  uint8_t enabled;
  int8_t radius;
  widget_t *next_widget;
  struct screen_t *parent;
  void (*draw)(widget_t*);
  void (*update)(widget_t*);
  void *content;                                           //<-- void *content
};

--- End code ---


Well, it looks a lot but it's not. In widget_t,  use void *content to allow any type of pointer.

comboBox_widget_t includes a selectable_widget_t,  And pointers to item, that are added when configuring it.

The allocating function is pretty simple. Of course the code is stripped down to show only what matters:

--- Code: ---widget_t *newWidget(widgetType type){
  widget_t *w=malloc(sizeof(widget_t));
  if(!w) Error_Handler();
  switch(type){
    case widget_combo:
      w->content = malloc(sizeof(comboBox_widget_t));
      break;
    default:
      Error_Handler();
  }
  if(!w->content) Error_Handler();
  widgetDefaultsInit(w, type);
  return w;
}

--- End code ---

The part that causes the hard fault is in widgetDefaultsInit:

--- Code: ---void widgetDefaultsInit(widget_t *w, widgetType type){
    if(type==widget_combo){   
        comboBox_widget_t *combo = (comboBox_widget_t*)w->content;

        w->frameType = frame_combo;
        w->draw = &comboBoxDraw;
        w->parent->current_widget = w;

        # These cause a hard fault! But doesn't with static allocation (Manually declaring each widget and sub-widget)
        combo->first = NULL;
        combo->currentItem = NULL;
        combo->selectable.processInput = &comboBoxProcessInput;
        combo->font = default_font;
        combo->currentScroll = 0;
    }
}

--- End code ---

DavidAlfa:

--- Quote from: evb149 on July 29, 2021, 01:08:12 am ---Error handler better be terminal or this will cause an uninitialized access after default case falls through:
 if(!w->content) Error_Handler();

Is parent initialized before this?
w->parent->current_widget = w;

--- End quote ---
That was it! Not exactly that, but yes, I over-simplified the function and it was missing an important step.
I kept looking at the malloc thing,"there must be something wrong with a pointer or a cast! ", but didn't made sense because it looked correct.
Yes, Error_Handler is terminal. It shows the file/line where the problem happened and dies in a forever loop.
Thanks!

TheCalligrapher:

--- Quote from: DavidAlfa on July 29, 2021, 12:45:25 am ---The allocating function is pretty simple. Of course the code is stripped down to show only what matters:

--- Code: ---widget_t *w=malloc(sizeof(widget_t));

--- End code ---

--- End quote ---

What programming language is that? The above code is invalid in both C and C++.

In C++ you would be required to explicity cast the result of `malloc` to `widget_t *`.

In C you would have to refer to your type as `struct widget_t`.

SiliconWizard:

--- Quote from: DavidAlfa on July 29, 2021, 05:19:40 am ---
--- Quote from: evb149 on July 29, 2021, 01:08:12 am ---Error handler better be terminal or this will cause an uninitialized access after default case falls through:
 if(!w->content) Error_Handler();

Is parent initialized before this?
w->parent->current_widget = w;

--- End quote ---
That was it! Not exactly that, but yes, I over-simplified the function and it was missing an important step.
I kept looking at the malloc thing,"there must be something wrong with a pointer or a cast! ", but didn't made sense because it looked correct.

--- End quote ---

I've noticed many people tend to run into the same issue as you did when debugging a problem (not just with code!): a tendency to focus on something they are not very confident in, rather than taking a look at the whole picture and using a methodic approach. In other words, they let prejudice rule over method.

Don't feel bad though, it's actually very common, and I've seen many threads in the same vein, with a lot of replies just making wild guesses all over the place, most of them unrelated to the issue (for lack of information), but the discussion itself is often enough for the OP to eventually find the culprit. Sharing a problem often helps us solve it by ourselves!

DavidAlfa:
I do that a lot! It happens all the time, something right in front of your eyes and you don't see it!
It actually was very simple. Previously there was a secondary function that was called before widgetDefaultsInit which initialized the parent pointer.
I packed everything in a single funcion, but missed that part. Everything else was fine!  :-+

I decided to ask here after few hours of code checking, testing, debugging and smashing the table.
Specially smashing the table and screaming things that should never said in presence of children ;D

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod