Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++: error: base class has a flexible array member

Tags:

c++

clang

I have upgraded my work environment from ubuntu 12.04 to 14.04. This led to an upgrade of my compiler clang from 3.0-6ubuntu3 to 3.4-1ubuntu3.

When I compile my code now I am getting an error I didn't use to get:

error: base class has a flexible array member

I followed the code and I found that I'm using inotify.h:

#include <sys/inotify.h>

Inside this file lies this struct:

struct inotify_event {
    int     wd;     /* watch descriptor */
    uint32_t        mask;       /* watch mask */
    uint32_t        cookie;     /* cookie to synchronize two events */
    uint32_t        len;        /* length (including nulls) of name */
    char        name __flexarr; /* stub for possible name */
};

Next, I read about the __flexarrhere but I didn't manage to understand what goes wrong or how can I fixed it. Any help will be appreciated.


UPDATE: As a follow-up to BobTFish answer, here is the use of inotify_event in my code.

I have a class named inotify_condition_c which has a member of type inotify_event let's call it m_notify_event.

I have several classes that inherited from inotify_condition_c. The compilation error clang returns is directed to those derived classes.

This is not a new piece of cod it is in our repo for quite long time. I am still don't understand why the upgrade from ubuntu 12.04 to 14.04 (and clang new version as well) revealed that error.

like image 978
Andy Thomas Avatar asked Dec 02 '25 07:12

Andy Thomas


1 Answers

__flexarr is a C trick where you place an empty array at the end of a struct, and then place the data you want immediately after an instance of that struct, so you can treat the extra data like part of the array. So for inotify_event:

|wd|mask|cookie|len|name|some|extra|data|
                         ^^^^^^^^^^^^^^^ can be accessed with name[0], name[1], etc.

When you have one class inherit from another:

struct Base {
    int a;
};
struct Derived : Base {
    int b;
}

it will (usually) be laid out in memory such that the data for Derived immediately follows the data for Base: |a|b|

It should be clear that these two techniques are incompatible. Therefore it seems clang has introduced an error for when you try to derive from a class using a flexible array, such as inotify_event does.

Somewhere in your code, something is inheriting from inotify_event. You can't do that.

Until we see that class, however, we can't suggest how to fix it. If you could find that class, edit it into your question, and explain how it is used, we might be able to help further.

Edit:
The least-bad (i.e. doesn't involve some level of UB) solution I can think of off the top of my head is to store the inotify_event outside of your class, by allocating it dynamically. Store a std::unique_ptr<inotify_event> member in your class, and set it with std::make_unique<inotify_event>(). Then treat this like a normal pointer, but don't worry about new/delete.

So it involves an extra allocation, but the other solution I can think of involves a dummy class that looks almost like inotify_event, and a very dubious cast.

Another possibility is to store the data needed to reconstruct an inotify_event, and create a new one locally each time you need it. I don't know if lifetime issues will allow this in your case.

like image 134
BoBTFish Avatar answered Dec 04 '25 20:12

BoBTFish



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!