3

When I try and run my program I get this warning and some weird bugs. rmi_pdu in the following structure contains a variable sized array which I want to access.

struct rmi_message_s {  /* Queue element containing Rmi message */
  struct rmi_message_s          *hnext;
  struct rmi_message_s          *hprev;
  uint16_t                      gen_counter;   /* Generation counter */
  time_value                    send_time;
  uint8_t                       retry_count;
  TAILQ_ENTRY(rmi_message_s)    rmi_message_next;
  rmi_message_pdu               rmi_pdu; /* contains a variable sized array */ 
};

typedef struct {
  uint16_t        zero;
  uint16_t        type;
  uint8_t         version;
  uint8_t         len;
  uint8_t         protocol;
  uint16_t        edge_port;
  uint16_t        core_port;
  uint32_t        connexus_id;
  pi_ipv4_addr_t  edge_addr;
  pi_ipv4_addr_t  core_addr;
  uint16_t        gen_count;     /* Integer to identify a stale packet */
  uint8_t         payload[];
} rmi_message_pdu;

the problem is when I am trying to free the memory which I am dynamically allocating. The contents are there but the free() API is abort()ing . This what the core looks like

in raise () from /lib64/libc.so.6
in abort () from /lib64/libc.so.6
in __libc_message () from /lib64/libc.so.6
in _int_free () from /lib64/libc.so.6
in free () from /lib64/libc.so.6
in free (p=0x2aaabc000fa0) at mallocdbg.cc:188
in rmi_hash_cleanup (rmi_msg=0x2aaabc000fa0) at tcpsvc_rmi.c:126
in rmi_process_response (response_packet=0x27422e00) at tcpsvc_rmi.c:239
in rmi_message_handle (pkt=0x27422e00 "", cnt=28) at tcpsvc_base.c:154
in udpif_worker (arg=0x2b01f7014340) at rumpnet_virtif/if_udp_netbsd_guest.c:573
in threadbouncer (arg=0x2b01f7016428) at rumpkern/emul.c:428
in clone () from /lib64/libc.so.6

This is what the allocation looks like. The caller who wants to use rmi, will pass the size as an argument.

struct rmi_message_s *rmi_msg;
rmi_msg = (struct rmi_message_s *) malloc (sizeof(struct rmi_message_s *) + len * sizeof(uint8_t));

len is passed as an argument.

siery
  • 467
  • 3
  • 20
Nikhil
  • 2,168
  • 6
  • 33
  • 51
  • Are you linking code compiled with an older version of GCC with your code (and passing that structure to/from it)? – derobert Jan 16 '12 at 17:03
  • Have you rebuilt your entire project using GCC 4.4 or later? That warning should only be relevant if some of your code was compiled using an older version of GCC and some of your code was compiled using a newer version. If that's *not* the case, then the problem is something else. – ruakh Jan 16 '12 at 17:05
  • How are you allocating `rmi_message_pdu`? How are you calculating the size to allocate? – MSN Jan 16 '12 at 17:24
  • I have edited the question. Please find it there – Nikhil Jan 16 '12 at 17:29

2 Answers2

5

You are not allocating enough memory:

struct rmi_message_s *rmi_msg ;
    rmi_msg = (struct rmi_message_s *) malloc
           (sizeof(struct rmi_message_s) + len * sizeof(uint8_t));

You had ...sizeof(struct rmi_message_s *)..., but it should have been ...sizeof(struct rmi_message_s)...

Aaron McDaid
  • 26,501
  • 9
  • 66
  • 88
  • Oh god! What a stupid mistake! thanks a lot for pointing that out :) – Nikhil Jan 16 '12 at 17:52
  • No problem, anyone can make that mistake. It's just one bug. That warning looks worrying also though. If you are still getting the warning, you should still ask about it (I'm no expert on ABIs). – Aaron McDaid Jan 16 '12 at 17:54
3

You almost certainly don't want to pass this object by value. Pass a pointer or reference to the object instead.

The warning is because if you are mixing code from GCC 4.3 or earlier, and GCC 4.4 or newer, they are incompatible in regards to how they would pass that struct on the stack. At any rate, I'm pretty sure you don't actually want to pass that on the stack anyway. It'd be hugely inefficient, and you'd lose your payload.

StilesCrisis
  • 15,972
  • 4
  • 39
  • 62
  • Re: "*and* you'd lose your payload": That makes sense, but . . . it seems like the whole reason there even *is* an ABI for these is that it must be trying to pass in the payload somehow. No? – ruakh Jan 16 '12 at 17:07
  • that's right.. I am using malloc and pointers to allocate..Everything seems to fine.. The probelem is there when I am trying to free the memory. It is asserting when I am trying to free this block! – Nikhil Jan 16 '12 at 17:08
  • @Nikhil: It sounds like you need to add more specifics to your question about the actual problem you're experiencing. We can't help you if you aren't specific about what is wrong. – StilesCrisis Jan 16 '12 at 17:11
  • @ruakh: I'm not an expert on VLA behavior in GCC, but I'd expect that it could only pass VLAs correctly where the size is known to the compiler at the point of being passed (e.g. a C99 style VLA). However I don't think there would be any way for GCC to know the size of the payload in this case (where the struct has no info; the size is just based on how big of a buffer you asked `malloc` for). – StilesCrisis Jan 16 '12 at 17:13
  • I have put some more info in the question – Nikhil Jan 16 '12 at 17:36
  • @StilesCrisis: That makes sense. I didn't think there even *were* cases where the size of a flexible array member is known at compile-time -- keeping in mind that flexible array members and variable-length arrays, despite their similarities, are actually two completely separate features -- but it turns out that GCC 3.0+ has, as a language extension, a static initializer syntax for stack-allocated structures with flexible array members. So I suppose the ABI must be relevant to just that one case. – ruakh Jan 16 '12 at 18:25