1

I would like to reserve some memory space on the heap and access it with a pointer.

The code run fine in C++ but I cannot compile it in C.

#include <string.h>
#include <stdlib.h>

#define IMG_WIDTH 320

struct cluster_s
{
  uint16_t size;
  uint16_t xMin;
  uint16_t xMax;
  uint16_t yMin;
  uint16_t yMax;
};

static struct cluster_s* detectPills(const uint16_t newPixel[])
{

  static struct cluster_s **pixel = NULL;
  static struct cluster_s *cluster = NULL;

  if(!pixel){
    pixel = (cluster_s**) malloc(IMG_WIDTH * sizeof(struct cluster_s*));
    if(pixel == NULL){
      return NULL;
    }
  }
  if(!cluster){
    cluster = (cluster*) malloc((IMG_WIDTH+1) * sizeof(struct cluster_s));
    if(cluster == NULL){
      return NULL;
    }
    for(int i=0; i<IMG_WIDTH;i++){
      memset(&cluster[i], 0, sizeof(cluster[i]));
      pixel[i] = &cluster[i];
    }
  }
(...)
}

which gives me the following compilation error:

error: 'cluster_s' undeclared (first use in this function) pixel = (cluster_s**) malloc(IMG_WIDTH * sizeof(struct *cluster_s));

If I comment out the two malloc calls, I am able to compile it. I also tried to remove the cast before malloc and got the compilation error:

In function _sbrk_r': sbrkr.c:(.text._sbrk_r+0xc): undefined reference to_sbrk' collect2: error: ld returned 1 exit status

EDIT: The proposed answers are correct, the problem comes from the linker which do not find sbrk

Florian K
  • 92
  • 9
  • 3
    `(cluster_s*)` ==> `(struct cluster_s*)` but in C you should not need the casts anyway. If you get a compilation error after removing the casts then it's not C compiler, perhaps the file is .cpp. – Weather Vane Jul 30 '19 at 09:40
  • Adding (struct cluster_s*) gives me the same error I get without casting. ie: In function _sbrk_r': sbrkr.c:(.text._sbrk_r+0xc): undefined reference to_sbrk' collect2: error: ld returned 1 exit status – Florian K Jul 30 '19 at 09:52
  • You must change `(cluster_s**)` on another line too. – Weather Vane Jul 30 '19 at 09:53
  • Yes I did it too. – Florian K Jul 30 '19 at 09:58

2 Answers2

1

This

I also tried to remove the cast before malloc and got the compilation error:

and this

The code run fine in C++ but I cannot compile it in C.

contradict each other.

The first one means that you are trying to compile the program as a C++ program.

To make the program to compile as a C++ program and as a C program there are two approaches.

The first one is everywhere in the program to use the type specifier struct cluster_s instead of just cluster_s . For example

pixel = (struct cluster_s**) malloc(IMG_WIDTH * sizeof(struct cluster_s*));
         ^^^^^^^^^^^^^^^^  
//...
cluster = (struct cluster*) malloc((IMG_WIDTH+1) * sizeof(struct cluster_s));
           ^^^^^^^^^^^^^^

The second one is to introduce an alias for the type specifier struct cluster_s like

typedef struct cluster_s cluster_s;
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Both possibilities give me compilation error: In function `_sbrk_r': sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk' collect2: error: ld returned 1 exit status – Florian K Jul 30 '19 at 09:59
  • @FlorianK what is the apostrophe for? Where is function `_sbrk_r'`? – Weather Vane Jul 30 '19 at 10:01
  • 1
    @FlorianK It has nothing common with the question you asked. Undefined error means that the compo;er does not see the definition of _sbrk (or sbrk ) – Vlad from Moscow Jul 30 '19 at 10:01
  • @WeatherVane @Vlad from Moscow The full error is: Compiling camera.c Linking build/ch.elf /home/flo/bin/gcc-arm-none-eabi-7-2018-q2-update/bin/../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m/fpv4-sp/hard/libg.a(lib_a-sbrkr.o): In function `_sbrk_r': sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk' collect2: error: ld returned 1 exit status lib/ChibiOS/os/common/startup/ARMCMx/compilers/GCC/mk/rules.mk:204: recipe for target 'build/ch.elf' failed make: *** [build/ch.elf] Error 1 – Florian K Jul 30 '19 at 10:10
  • 2
    Isn't `error: ld` from the *linker*? That means there were no compilation errors. – Weather Vane Jul 30 '19 at 10:12
  • @FlorianK As I said the linker does not see the definition of sbrk. – Vlad from Moscow Jul 30 '19 at 10:12
  • Yes it seems that it is a linker problem. Without malloc call I can compile normally @WeatherVane – Florian K Jul 30 '19 at 10:21
  • So if you are porting from C++ you need the right libraries. – Weather Vane Jul 30 '19 at 10:23
0

Replace

struct cluster_s
{
   ...
};

with

typedef struct cluster_s 
{
    ....
}cluster_s;

In C++, a struct and a Class are analogous and can be used interchangeably for the most part. So cluster_s and struct cluster_s can both be used.

In C, cluster_s is not defined. The change above will define a type of the same name.

You can see the answer When should you use a class vs a struct in C++? for the differences between a class and a struct.

Rishikesh Raje
  • 8,556
  • 2
  • 16
  • 31
  • I guess I should have phrased my question differently, I always get the same strange error after using any of the correct proposed answer to properly call malloc. The error is: In function `_sbrk_r': sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk' collect2: error: ld returned 1 exit status – Florian K Jul 30 '19 at 10:05
  • You can go through https://stackoverflow.com/questions/28895703/sbrk-function-not-found-when-placed-in-a-static-library. Possibly it will solve the `_srbk` issue – Rishikesh Raje Jul 30 '19 at 10:20