dereferencing pointer to incomplete type

CStructCompiler ErrorsTypedefDereference

C Problem Overview


I've seen a lot of questions on this but I'm going to ask the question differently without specific code. Is there a way of EASILY determining what is causing the type to be incomplete? In my case I'm using someone elses code and I'm completely sure I don't have the headers right, but (since computers do this stuff much faster and better than human eyeballs) is there a way to get the compiler to say, "hey you think you have type X at line 34 but that's actually missing." The error itself only shows up when you assign, which isn't very helpful.

C Solutions


Solution 1 - C

I saw a question the other day where someone inadvertently used an incomplete type by specifying something like

struct a {
    int q; 
}; 
struct A *x; 
x->q = 3;

The compiler knew that struct A was a struct, despite A being totally undefined, by virtue of the struct keyword.

That was in C++, where such usage of struct is atypical (and, it turns out, can lead to foot-shooting). In C if you do

typedef struct a {
    ...
} a;

then you can use a as the typename and omit the struct later. This will lead the compiler to give you an undefined identifier error later, rather than incomplete type, if you mistype the name or forget a header.

Solution 2 - C

Another possible reason is indirect reference. If a code references to a struct that not included in current c file, the compiler will complain.

>a->b->c //error if b not included in current c file

Solution 3 - C

What do you mean, the error only shows up when you assign? For example on GCC, with no assignment in sight:

int main() {
    struct blah *b = 0;
    *b; // this is line 6
}

incompletetype.c:6: error: dereferencing pointer to incomplete type.

The error is at line 6, that's where I used an incomplete type as if it were a complete type. I was fine up until then.

The mistake is that you should have included whatever header defines the type. But the compiler can't possibly guess what line that should have been included at: any line outside of a function would be fine, pretty much. Neither is it going to go trawling through every text file on your system, looking for a header that defines it, and suggest you should include that.

Alternatively (good point, potatoswatter), the error is at the line where b was defined, when you meant to specify some type which actually exists, but actually specified blah. Finding the definition of the variable b shouldn't be too difficult in most cases. IDEs can usually do it for you, compiler warnings maybe can't be bothered. It's some pretty heinous code, though, if you can't find the definitions of the things you're using.

Solution 4 - C

I don't exactly understand what's the problem. Incomplete type is not the type that's "missing". Incompete type is a type that is declared but not defined (in case of struct types). To find the non-defining declaration is easy. As for the finding the missing definition... the compiler won't help you here, since that is what caused the error in the first place.

A major reason for incomplete type errors in C are typos in type names, which prevent the compiler from matching one name to the other (like in matching the declaration to the definition). But again, the compiler cannot help you here. Compiler don't make guesses about typos.

Solution 5 - C

this error usually shows if the name of your struct is different from the initialization of your struct in the code, so normally, c will find the name of the struct you put and if the original struct is not found, this would usually appear, or if you point a pointer pointed into that pointer, the error will show up.

Solution 6 - C

A - Solution

Speaking for C language, I've just found ampirically that following declaration code will be the solution;

typedef struct ListNode
{
	int data;
	ListNode * prev;
	ListNode * next;
} ListNode;

So as a general rule, I give the same name both for both type definition and name of the struct;

typedef struct X
{
	// code for additional types here
	X* prev; // reference to pointer
	X* next; // reference to pointer
} X;

B - Problemetic Samples

Where following declarations are considered both incomplete by the gcc compiler when executing following statement. ;

removed->next->prev = removed->prev;

And I get same error for the dereferencing code reported in the error output;

>gcc Main.c LinkedList.c -o Main.exe -w
LinkedList.c: In function 'removeFromList':
LinkedList.c:166:18: error: dereferencing pointer to incomplete type 'struct ListNode'
     removed->next->prev = removed->prev;

For both of the header file declarations listed below;

typedef struct
{
	int data;
	ListNode * prev;
	ListNode * next;
} ListNode;

Plus this one;

typedef struct ListNodeType
{
	int data;
	ListNode * prev;
	ListNode * next;
} ListNode;

Solution 7 - C

Outside of possible scenarios involving whole-program optimization, the code code generated for something like:

struct foo *bar;
struct foo *test(struct foo *whatever, int blah)
{
  return blah ? whatever: bar;
}

will be totally unaffected by what members struct foo might contain. Because make utilities will generally recompile any compilation unit in which the complete definition of a structure appears, even when such changes couldn't actually affect the code generated for them, it's common to omit complete structure definitions from compilation units that don't actually need them, and such omission is generally not worthy of a warning.

A compiler needs to have a complete structure or union definition to know how to handle declarations objects of the type with automatic or static duration, declarations of aggregates containing members of the type, or code which accesses members of the structure or union. If the compiler doesn't have the information needed to perform one of the above operations, it will have no choice but to squawk about it.

Incidentally, there's one more situation where the Standard would allow a compiler to require a complete union definition to be visible but would not require a diagnostic: if two structures start with a Common Initial Sequence, and a union type containing both is visible when the compiler is processing code that uses a pointer of one of the structure types to inspects a member of that Common Initial Sequence, the compiler is required to recognize that such code might be accessing the corresponding member of a structure of the other type. I don't know what compilers if any comply with the Standard when the complete union type is visible but not when it isn't [gcc is prone to generate non-conforming code in either case unless the -fno-strict-aliasing flag is used, in which case it will generate conforming code in both cases] but if one wants to write code that uses the CIS rule in such a fashion as to guarantee correct behavior on conforming compilers, one may need to ensure that complete union type definition is visible; failure to do so may result in a compiler silently generating bogus code.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnickView Question on Stackoverflow
Solution 1 - CPotatoswatterView Answer on Stackoverflow
Solution 2 - CSteeven LiView Answer on Stackoverflow
Solution 3 - CSteve JessopView Answer on Stackoverflow
Solution 4 - CAnTView Answer on Stackoverflow
Solution 5 - Ccatzilla_wawView Answer on Stackoverflow
Solution 6 - CLevent DiviliogluView Answer on Stackoverflow
Solution 7 - CsupercatView Answer on Stackoverflow