c - How to detect instances where code accidentally creates a pointer to a pointer? -


in doing wholesale refactoring, i've come across instances i've made same mistake. have accidentally passed pointer pointer instead of pointer.

code explains best. /* oops */ below.

the struct:

struct my_struct {     int x;     int y;     int z;     int value; } 

initialize function:

void initialize(struct my_struct *s) {     s->x = 0;     s->y = 0;     s->z = 0;     s->value = 0; } 

the original function:

struct my_struct do_something() {     struct my_struct s;      initialize(&s);      s.value = 27;      return s; } 

the new function

void do_something(struct my_struct *s) {     initialize(&s); /* oops! */      s->value = 27; } 

it should have been:

void do_something(struct my_struct *s) {     initialize(s); /* fixed */      s->value = 27; } 

is there way, maybe compiler flag or linter can me locate these oopsies?

notes: i'm using gcc (but if compiler or linter can find this, please tell)

i'm using these compiler flags , don't catch it:

cflags = \     -std=c89 \     -pedantic \     -pedantic-errors \     -werror \     -wextra \     -wmissing-prototypes \     -wall \     -wold-style-definition \     -wdeclaration-after-statement \     -wundef \     -wpointer-arith \     -wcast-qual \     -wcast-align \     -wfloat-equal \     -wno-missing-braces 

i have prototypes in header everything.

it's not standard picked -- c90. c99 , c11 take too.

$ gcc --version gcc (gcc) 6.1.1 20160621 (red hat 6.1.1-3) 

passing pointer pointer pointer expected must cause compiler error. cannot reproduce example suggesting (gcc 5.4.0, c99).

but there situation can cause kind of error:

foo.h:

struct foo {   int dummy; }; 

main.c:

#include "foo.h" void init(void *); int main() {   struct foo f;   struct foo * fp = &f;   init(&f);   init(&fp);   return 0; } 

init.c:

#include "foo.h" // need prototype because otherwise -wmissing-prototypes issues warning // such code not uncommon, though, when e.g. there // c preprocessor macros defining kinds of functions. void init(struct foo *f); void init(struct foo *f) {   f->dummy = 42; } 

this compiles fine without warning. translation unit main.c sees (wrong) declaration void init(void *) , emits no warning when passing different pointer types (as they're implicitly convertible void *). since c compilers don't mangle parameter types symbols of resulting object files, linker happily resolve reference function init main.o function symbol init in init.o.

[nix-shell:/tmp/wtf]$ nm init.o  0000000000000000 t init [nix-shell:/tmp/wtf]$ nm main.o                   u _global_offset_table_                  u init 0000000000000000 t main                  u __stack_chk_fail 

c++ compilers do mangle parameter types symbols, thus:

[nix-shell:/tmp/wtf]$ lang= g++ -wall -wextra main.c init.c  /run/user/1000/cctwt0nl.o: in function `main': main.c:(.text.startup+0x1d): undefined reference `init(void*)' main.c:(.text.startup+0x27): undefined reference `init(void*)' collect2: error: ld returned 1 exit status 

note: i'm not suggesting compile c code c++ compiler. don't that, please.


Comments

Popular posts from this blog

java - Jasper subreport showing only one entry from the JSON data source when embedded in the Title band -

serialization - Convert Any type in scala to Array[Byte] and back -

SonarQube Plugin for Jenkins does not find SonarQube Scanner executable -