1

I'm currently porting code that I wrote for some other embedded system to a STM Evalution Board (STM32F407). I used malloc in the following way on the old board (Simplified for clarity):

float* values = (float*)malloc(sizeof(float)*NO_OF_ATT);

values[0] = 1.0;
values[1] = 2.0;
values[2] = 3.0;
values[3] = 4.0;

This code was working as expected. However on the STM board when I run this code it seems that I cannot access the array in this way, instead of the values it just outputs values like 3.85205412e-034. I thought in C notation x[y] is equivalent to *(x + y)? Anybody can help me in trying to understand what's happening? Thanks in advance!

edit: Here is the non-simplified code:

    l = (dllist*)calloc(sizeof(dllist),0);

l->Distance = 0;

for (int i = 0; i < NO_OF_ATT; i++)
{
    l->Value[i] = featureValues[i];

    if (i == (NO_OF_ATT - 1))
    {
        l->Value[i] = (int)featureValues[i];
    }
}


sglib_dllist_add(&queryList, l);

The featureValues array has the correct values but l->value array doesn't. Screenshot:enter image description here

Edit 2:

Struct definition:

typedef struct dllist {
   float Value[NO_OF_ATT];
   float Distance;
   struct dllist *ptr_to_next;
   struct dllist *ptr_to_previous;
} dllist;

I just want to clarify: My code runs fine in Visual Studio and my second embedded system. It's just not working as expected on my STM board.

LPs
  • 16,045
  • 8
  • 30
  • 61
Unfixable
  • 440
  • 1
  • 7
  • 20
  • 2
    When you use Y as index, then yes.Don't cast malloc. Show us a code to understand how you exactly try to access that array. – Michi Sep 07 '15 at 05:14
  • @Michi , What is the reason that you are asking not to caste malloc ? Myself also learner so asking with curiosity – spt025 Sep 07 '15 at 05:32
  • Because return type of malloc is void*. In c you don't cast malloc. – Michi Sep 07 '15 at 05:33
  • @Michi .. Okay generally I use malloc that way by casting it to needed type eg. float * in this case.. But if we are doing casting in Calloc it is fine .. right ? – spt025 Sep 07 '15 at 05:37
  • 1
    @spr025 what's the return type of calloc? Read this http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – Michi Sep 07 '15 at 05:57
  • 1
    The problem is somewhere else in your code. Please post the whole thing instead of the simplified version. – japreiss Sep 07 '15 at 06:29
  • @japreiss: I posted the whole code part – Unfixable Sep 07 '15 at 08:13
  • @Unfixable What is `values` in relation to the code you just posted? Is that supposed to be the same as `featureValues`? – Lundin Sep 07 '15 at 08:20
  • Also why are you using dynamic allocation on a Cortex-M microcontroller? Didn't know it was possible to squeeze in a high-level OS on those. For most microcontroller applications, [dynamic allocation doesn't make any sense](http://electronics.stackexchange.com/questions/171257/realloc-wasting-lots-of-space-in-my-mcu/171581#171581). – Lundin Sep 07 '15 at 08:24
  • The legacy code I received uses dynamically allocated data structures stored in a linked lists. I think changing to stack allocated data is possible but it requires me increasing the stack size but I'm not sure if I have this option available. I guess changing to static allocation would resolve this problem but it was working before on an even weaker microcontroller. And yes its Cortex-M3 based – Unfixable Sep 07 '15 at 08:41
  • @Lundin: values doesn't have any direct relation. I just simplified the problem to a very simple allocation which also didn't work and reproduced the given problem in a very simple and direct way – Unfixable Sep 07 '15 at 08:42
  • You can allocate a static memory pool allocated in the `.data` segment. No need to use neither stack nor heap. Anyway, where is `featureValues` initialized then? Because that's what seems to be the problem, not the other code. Also please include the type definition for `dllist`. – Lundin Sep 07 '15 at 09:22
  • Cast ing `void *` hides potential type conflicts. So, you should never cast in C. `malloc` & friends return `void *`. Note that you also do not cast the reverse way, as for `free` and `realloc` argument. – too honest for this site Sep 07 '15 at 12:16
  • @Olaf : Thanks I will remove the cast! – Unfixable Sep 08 '15 at 01:02
  • @Lundin: Added the type definition. featureValues is initialized before and passed as a pointer (Heap allocated). However during the assignment ( l->Value[i] = featureValues[i];) I can see that featureValues stores the correct values, they just seem to be not stored in my "l" structure (type dllist). – Unfixable Sep 08 '15 at 01:11
  • I doubt anyone will be able to answer this question with the info given. Three most likely causes are: array-out-of-bounds or pointer-related bugs elsewhere in the code causing memory corruption, a stack overflow or the heap somehow being misconfigured or corrupt. I also noted that `l` (horrible variable name) has the address 0 in your debug screenshot. If this is because of memory corruption or because you are debugging optimized code (bad idea), I don't know. – Lundin Sep 08 '15 at 06:15

3 Answers3

2

You don't use calloc correctly:

l = (dllist*)calloc(sizeof(dllist),0);

void* calloc (size_t num, size_t size);

Allocates a block of memory for an array of num elements, each of them size bytes long, and initializes all its bits to zero.

You're asking for sizeof(dllist) zero-size elements. In other words, you request calloc to allocate zero bytes for you, and it returns a NULL pointer, as can be seen in your screenshot.

Try replacing the above calloc call with:

l = (dllist*)calloc(1,sizeof(dllist));
Sigve Kolbeinson
  • 1,133
  • 1
  • 7
  • 16
0
float* values = calloc(sizeof(float)*NO_OF_ATT,0);

values[0] = 1.0;
values[1] = 2.0;
values[2] = 3.0;
values[3] = 4.0;

This will initialize all variables with 0. Now use this to print the values...

printf("%f",values[<any index you wanna print>]);

It should print correctly, infact malloc will also do. but just let me know how you are printing (post those statements and output if still it is coming like this)

EDIT

In your Structure of l when you are declaring float array that time only you need to assign the memory for that one.After assigning memory to that float array

l = (dllist*)calloc(sizeof(dllist),0)

dllist is your structure...correct ? So when assigning memory to that one that time you array of whatever size you've mentioned in structure will get initilized.. Now when you are assigning the values use this syntax..

*(l->values[i]) = featureValues[i] ; 
           *or*
*(l.(values + i))  = featureValues[i] ; 

This should solve your problem

LPs
  • 16,045
  • 8
  • 30
  • 61
spt025
  • 2,134
  • 2
  • 20
  • 26
  • How zeroed memory will solve his problem and why? Btw do not cast void* in C, it's not *wrong* but if you *forget* #include you won't have a compile-time error (in general, not just with malloc or calloc). Also you should check calloc return value. – Adriano Repetti Sep 07 '15 at 05:49
  • Yeah , I understood the problem with it .. @AdrianoRepetti in comments Michi pointed me to one nice question. By the way what I felt is this person is getting garbage value so it might be better to initilize all values. Since his way of accessing these variables is not know even I'm asking for the same from author of question and thanks for pointing out cast related mistake of mine... – spt025 Sep 07 '15 at 06:11
  • Using calloc and initializing to 0 didn't make any difference – Unfixable Sep 07 '15 at 08:14
  • @AdrianoRepetti If you forget include you _will_ have a compile-time error. The C standard doesn't allow "default int" non-prototype functions any longer. – Lundin Sep 07 '15 at 08:18
  • @AdrianoRepetti Just get one which supports C99. Most embedded compilers support it nowadays. – Lundin Sep 07 '15 at 08:21
  • l is a structure in your code ...show that structure...problem is there. – spt025 Sep 07 '15 at 08:29
  • Yeah the (int) cast was legacy code which I didn't touch yet, Thank you for mentioning it. That field only stores integer variables but its cast to int and then saved in float. Seems useless to me. – Unfixable Sep 07 '15 at 08:36
  • The structure of l you can see in the screenshot already. Do you want the full definition? The screenshots shows all variables though. – Unfixable Sep 07 '15 at 08:37
  • Try this ... it may or may not work..not tested ...since l is pointer you just need to access it carefully...that is the only issue in this problem.. – spt025 Sep 07 '15 at 09:22
  • In general, code is preferred to screenshots. If we're trying to figure out what the compiler does, it's better to examine the compiler's input. In this situation though, the screenshot does add some additional information which I think may be useful - The value of `l` is `0x00000000`, i.e. it looks like your `calloc()` call failed. – Sigve Kolbeinson Sep 07 '15 at 11:18
  • @LPs : I tried your syntax and got the following error: ..\Src\motion\Classifier.cpp(66): error: #75: operand of "*" must be a pointer *(l->Value[i]) = featureValues[i]; – Unfixable Sep 08 '15 at 00:58
  • @Sigve Kolbeinson : I will add the struct to the question – Unfixable Sep 08 '15 at 01:00
0

As you can see in your debug screenshot the address of l variable is 0x00000000. This means that calloc returned NULL because of there is no room to allocate requested size.

First of all, each time you use malloc calloc and so on you MUST check its return value:

retPointer = malloc(sizeof(yourStruct);
if (retPointer == NULL) 
{ 
   // There wasn't room into heap memory
}

As for many MCUs address 0 is ISP (Initial Stack Pointer) and address 0x00000004 (in 32 bit memory space) is IPC (Initial Program Counter). Those addresses belongs to flash then cannot modifiable with a simple assignation.

If you try to display values of array[0] a and array[1] in HEX you could see your ISP and IPC values as programmed in your linker script.

LPs
  • 16,045
  • 8
  • 30
  • 61