argtable / argtable3

A single-file, ANSI C, command-line parsing library that parses GNU-style command-line options.
http://www.argtable.org
Other
372 stars 65 forks source link

Compilation error with optimization on ARM #53

Closed fedegiova closed 3 years ago

fedegiova commented 3 years ago

I got this error while compiling with -Wall on an ARM target:

../../src/Backup/src/argtable3.c: In function ‘trex_compile’:
../../src/Backup/src/argtable3.c:347:11: error: variable ‘ret’ might be clobbered by ‘longjmp’ or ‘vfork’ [-Werror=clobbered]
     void* ret = malloc(size);

The problem in in the function trex_compile which uses setjmp() to handle errors, on posix man setjmp states:

       The  compiler  may  optimize variables into registers, and longjmp() may restore the values of
       other registers in addition to the stack pointer and program counter.  Consequently, the  val‐
       ues of automatic variables are unspecified after a call to longjmp() if they meet all the fol‐
       lowing criteria:

       •  they are local to the function that made the corresponding setjmp() call;

       •  their values are changed between the calls to setjmp() and longjmp(); and

       •  they are not declared as volatile.

I've not found any way to satisfy the above requirements without changing the function signature, but I've solved the error disabling optimizations locally, this way the compiler (gcc 9.2) put the variable on the stack and the error get resolved.

At the function declaration:

TREX_API TRex* trex_compile(const TRexChar* pattern, const TRexChar** error, int flags) __attribute__((optimize(0)));  

I'm filing an issue because maybe someone has a better idea.

tomghuang commented 3 years ago

Hi @fedegiova , thanks for figuring out the root cause of this issue.

When you say, "disabling optimizations locally," do you mean that you disable optimizations for TRex, and still enable optimizations for the entire application? Did you do it by using some #pragma directives? Is it an acceptable solution for you?

fedegiova commented 3 years ago

Hi, with the attribute below the optimizations getsl disabled only for the function trex_compile, all the others get the optimization level specified on the command line.

TREX_API TRex* trex_compile(const TRexChar* pattern, const TRexChar** error, int flags) __attribute__((optimize(0)));

I've not found another way to force the variable to be allocated on the stack and not on the registers, unfortunately setjump saves only PC and SP so when returning from a longjmp call the values of the other registers are incoherent.

tomghuang commented 3 years ago

@fedegiova Thanks for this solution. I don't want to change the TRex implementation, so I will add the attribute to trex_compile when we compile with GCC.