Why do I get “warning: missing initializer for mem

2019-02-14 06:03发布

问题:

I'm wondering why I am getting an warning about initialization in one case, but not the other. The code is in a C++ source file, and using GCC 4.7 with -std=c++11.


struct sigaction old_handler, new_handler;

The above produces NO warnings with -Wall and -Wextra.


struct sigaction old_handler={}, new_handler={};
struct sigaction old_handler={0}, new_handler={0};

The above produces warnings:

warning: missing initializer for member ‘sigaction::__sigaction_handler’ [-Wmissing-field-initializers]
warning: missing initializer for member ‘sigaction::sa_mask’ [-Wmissing-field-initializers]
warning: missing initializer for member ‘sigaction::sa_flags’ [-Wmissing-field-initializers]
warning: missing initializer for member ‘sigaction::sa_restorer’ [-Wmissing-field-initializers]

I've read through How should I properly initialize a C struct from C++?, Why is the compiler throwing this warning: "missing initializer"? Isn't the structure initialized?, and bug reports like http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750. I don't understand why the uninitialized struct is not generating a warning, while the initialized struct is generating a warning.

Why is the uninitialized structs not generating a warning; and why is the initialized structs generating a warning?

回答1:

Here is a simple example:

#include <iostream>

struct S {
  int a;
  int b;
};

int main() {
  S s { 1 }; // b will be automatically set to 0
             // and that's probably(?) not what you want
  std::cout<<"s.a = "<<s.a<<", s.b = "<<s.b<<std::endl;
}

It gives the warning:

missing.cpp: In function ‘int main()’:
missing.cpp:9:11: warning: missing initializer for member 'S::b' [-Wmissing-field-initializers]

The program prints:

s.a = 1, s.b = 0

The warning is just a reminder from the compiler that S has two members but you only explicitly initialized one of them, the other will be set to zero. If that's what you want, you can safely ignore that warning.

In such a simple example, it looks silly and annoying; if your struct has many members, then this warning can be helpful (catching bugs: miscounting the number of fields or typos).


Why is the uninitialized structs not generating a warning?

I guess it would simply generate too much warnings. After all, it is legal and it is only a bug if you use the uninitialized members. For example:

int main() {
  S s;
  std::cout<<"s.a = "<<s.a<<", s.b = "<<s.b<<std::endl;
}

missing.cpp: In function ‘int main()’:
missing.cpp:10:43: warning: ‘s.S::b’ is used uninitialized in this function [-Wuninitialized]
missing.cpp:10:26: warning: ‘s.S::a’ is used uninitialized in this function [-Wuninitialized]

Even though it did not warn me about the uninitialized members of s, it did warn me about using the uninitialized fields. All is fine.

Why is the initialized structs generating a warning?

It warns you only if you explicitly but partially initialize the fields. It is a reminder that the struct has more fields than you enumerated. In my opinion, it is questionable how useful this warning is: It can indeed generate too much false alarms. Well, it is not on by default for a reason...



回答2:

That's a defective warning. You did initialize all the members, you just didn't have the initializers for each member separately appear in the code.

Just ignore that warning, if you know what you are doing. I regularly get such warnings too, and I'm upset regularly. But there's nothing I can do about it but to ignore it.

Why is the uninitialized struct not giving a warning? I don't know, but most probably that is because you didn't try to initialize anything. So GCC has no reason to believe that you made a mistake in doing the initialization.



回答3:

The compiler warns that all members are not initialized when you initialize the struct. There is nothing to warn about declaring an uninitialized struct. You should get the same warnings when you (partially) initialize the uninitialized structs.

struct sigaction old_handler, new_handler;
old_handler = {};
new_handler = {};

So, that's the difference. Your code that doesn't produce the warning is not an initialization at all. Why gcc warns about zero initialized struct at all is beyond me.



回答4:

The only way to prevent that warning ( or error, if you or your organization is treating warning as error (-Werror option)) is to memset it to init value. For example:

#include <stdio.h>
#include <memory.h>

typedef struct {
    int a;
    int b;
    char c[12];
} testtype_t;

int main(int argc, char* argv[]) {
    testtype_t type1;

    memset(&type1, 0, sizeof(testtype_t));

    printf("%d, %s, %d\n", argc, argv[0], type1.a);
    return 0;
}

Not very clean, however, seems like that for GCC maintainers, there is only one way to initialize a struct and code beauty is not on top of their list.



回答5:

You're solving the symptom but not the problem. Per my copy of "Advanced Programming in the UNIX Environment, Second Edition" in section 10.15:

Note that we must use sigemptyset() to initialize the sa_mask member of the structure. We're not guaranteed that act.sa_mask = 0 does the same thing.

So, yes, you can silence the warning, and no this isn't how you initialize a struct sigaction.