On Tue, Mar 23, 2021 at 8:39 PM Matias N. <mat...@imap.cc> wrote:

> Hi,
> while using getopt() from a task started from NSH I realized subsequent
> calls reused the global optind and similar variables resulting in different
> results each time. I'm aware this is expected in FLAT mode and is related
> to the issue of static C++ constructors (they would only be called once,
> not every time the task is started).
>
> What I wonder is what could we do to avoid this common pitfall:
> - document it somewhere (a common issues/troubleshooting section in the
> docs would be good to have anyways) and just accept the issue
> - religiously initialize globals myself before being used (a pain, error
> prone, and a bit adhoc, working only for FLAT mode)


When using globals, best practice is to make it really clear that the
variables are global. Many programmers do this by prefixing global variable
names with g_*.

I take a different approach: A long time ago, I started grouping all
globals in a struct, which has one global instance called Global. It makes
it easy to find all globals, and furthermore at the start of the program as
a matter of policy the first thing I do is memset() the Global struct to 0.
Yes, I know that is often redundant to the startup code, but in some
situations the startup code doesn't initialize globals. The FLAT model is
one example of this (from the 2nd invocation onwards). I've seen other
examples of this over the years. By memset()ing your globals at the start
of main() you can rest assured that the globals are in fact zeroed,
regardless of whatever else happened before main(). It has another side
benefit: with globals grouped this way, it becomes trivial to take a
standalone program and turn it into a component of a larger program.
tl;dr, this
approach has worked great for me for a long time.

Caveat: It won't help if your program (or any API called by it) uses
globals that are outside your control, and therefore, not initialized by
you. :-/

Nathan

Reply via email to