Ошибка dereferencing pointer to incomplete type

Да, всё верно, и не только для gcc, а и вообще для любого компилятора для C либо C++.

Весь код распознаётся так или иначе сверху-вниз, слева-направо (конкретно GCC использует Flex в совокупности с GNU Bison либо yacc, при этом используется LALR-алгоритм). При ипользовании имени структуры до того, как она была объявлена, то компилятор не сможет её распознать т. к. ещё не встречал её объявления.

void f(struct my_struct *a) {} // ошибка компиляции - my_struct неизвестна
//.....
struct my_struct { int b; };  // непосредственно определение структуры

Если же объявить структуру, но определить её в коде позже, то компилятор не будет знать ничего о ней, и соответственно будет ограничен при парсинге выражений с её участием — не сможет выделить необходимую память, доступиться к какому-либо её элементу

struct my_struct; //мы указываем компилятору, что где-то ниже должна быть определена структура с именем my_struct.
void f(struct my_struct *a) { // всё отлино, мы знаем, что ниже должна быть структура с таким именем.
    a->b; } //ошибка компиляции - у компилятора нет сведений, что структура my_struct содержит поле b
struct my_struct { int b; };  // непосредственно определение структуры

  1. Causes of the dereferencing pointer to incomplete type Error in C
  2. Incomplete Types in C
  3. Referencing and Dereferencing a Pointer in C
  4. Solve the dereferencing pointer to incomplete type Error in C
  5. Conclusion

Dereferencing Pointer to Incomplete Type Error in C

It is known that a pointer is used to store the address of values stored inside a variable. This pointer variable can be referenced to a variable to get its address or dereferenced to access its value.

But when this pointer needs to be seen or edited, it must be dereferenced. When this dereferencing is done through a declared but not defined type, it throws the error dereferencing pointer to incomplete type.

Causes of the dereferencing pointer to incomplete type Error in C

This error is caused when the compiler comes across a pointer being dereferenced to a struct. When the compiler moves towards the struct, it finds it incomplete, i.e., not defined properly.

The compiler throws different errors when an undefined struct is called to deference a pointer. The type of error encountered depends on the compiler used.

the dereferencing pointer to incomplete type Error in GCC Compiler

For example, an undefined struct looks like this:

struct circle {
	int length;
};
int main() {
    struct round *x = 0;
    *x;
}

In the above C program, it can be observed that a struct circle is constructed, but the struct called inside the main function has the name round.

Inside the main function, an object pointer *x is created from the struct round. Lastly, the pointer object is called.

Here, an incomplete struct is used as if it is a complete struct, which causes the compiler to throw the error.

1035906452/source.c: In function 'main':
1035906452/source.c:6:5: error: dereferencing pointer to incomplete type 'struct round'
     *x;
     ^~

It can be observed that the compiler throws the error dereferencing pointer to incomplete type.

Normally, C will find the name of the struct which was put in; if the original struct is not found, this would usually appear. It will also appear if you point a pointer pointed into that pointer.

This error typically appears if the name of your struct is different from the initialization of your struct in the code.

A struct can also throw errors when given an alias that the compiler cannot read, but that does not happen with every compiler.

the dereferencing pointer to incomplete type Error in Clang Compiler

This is encountered when the same code is run through a Clang compiler.

1790191360/source.c:6:5: error: incomplete type 'struct round' where a complete type is required
    *x;
    ^
1790191360/source.c:5:12: note: forward declaration of 'struct round'
    struct round *x = 0;
           ^
1790191360/source.c:6:5: warning: expression result unused [-Wunused-value]
    *x;
    ^~
1 warning and 1 error generated.

Here, the compiler calls out the incomplete struct but leaves the dereferenced pointer as a warning instead of an error.

Understanding why the error dereferencing pointer to incomplete type happens requires knowing two concepts.

  1. What are incomplete types?
  2. What does dereferencing a pointer mean?

Incomplete Types in C

A type declared but not specified is incomplete (in the case of struct types).

Typos in type names, which prevent the compiler from matching one name to the other, are a common cause of incomplete type errors in the C language (like in matching the declaration to the definition).

It is a misconception to think that an incomplete type is a missing type. Incomplete types can occur outside struct too.

Three scenarios cause incomplete type:

  1. A struct type with no members.
  2. A union type with no members.
  3. An array that is declared but no element is inserted.

Create an Incomplete Type and Define It

A struct or a type that is similar needs to be specified with the information lacking to complete an incomplete type.

The creation and completion of the incomplete types are demonstrated in the examples below.

Declare a structure type but omit the members to produce an incomplete structure type. The x pointer in this illustration points to an incomplete structure type named library.

Declare the same structure type later in the same scope with its members provided to complete an incomplete structure type.

struct library
{
    int book_id;
    char book_name[50];
}

To create an array of incomplete types, declare an array type without specifying its repetition count. For instance:

char book_name[];  /* book_name has incomplete type */

Declare the same name later in the same scope with its repetition count set to finish an incomplete array type.

char book_name[25]; /* book_name now has complete type */

Once we have understood how incomplete types are completed, we can go to the second part of solving the dereferencing pointer to incomplete type error.

Referencing and Dereferencing a Pointer in C

The function of a pointer is to store the address of a value, which means it stores a reference to something. The object to which a pointer point is called a pointee.

Referencing a Pointer in C

There are two distinct stages involved in allocating a pointer and a pointee to which it will point. The pointer/pointee structure can be thought of as having two levels of operation.

Everything needs to be set up on both levels for it to work. The most frequent mistake is to focus on writing code that manipulates the pointer level while neglecting to set up the pointee level.

Pointer operations that do not contact the pointees are sometimes referred to as “shallow” operations, while those that do are referred to as “deep” operations.

Consider the following code:

A pointer ptr_a is created inside the main function. This pointer is created but cannot store something unless a pointee or a memory chunk is allocated.

The allocation of memory is done by malloc, and the size given is equivalent to data type int.

void main() {
    int*    ptr_a;  // Allocate the pointer

    ptr_a = malloc(sizeof(int));    // Allocate an int pointee, and set ptr_a to point to it
}

C++ code:

int main() {
    int*    ptr_a;  // Allocate the pointer ptr_a

    ptr_a = new int;    // Allocate an int pointee, and set ptr_a to point to it
}

Dereferencing a Pointer in C

Dereference operations begin at the pointer and follow up to the pointee. The objective could be to examine or modify the pointee state.

A pointer can only be dereferenced if it has a pointee; the pointee must also be allocated before the pointer can be made to point at it. Forgetting to set up the pointee is the most frequent mistake in pointer programs.

Failure in code to successfully dereference a pointer is the most common runtime crash. The runtime system in Java flags the issue of improper dereferences with minor warnings.

In compiled languages like C and C++, a bad dereference can cause a crash or cause spontaneous memory corruption. This makes it challenging to find pointer issues in compiled languages.

C code:

Once the memory is allocated and pointed towards pointer ptr_a, a value is stored inside it by dereferencing it.

void main()  {
	int*    ptr_a;

	ptr_a = malloc(sizeof(int));    // Allocate an int pointee, and set ptr_a to point to it

	*ptr_a = 42;    // Dereference ptr_a to store 42 in its pointee
}

C++ code:

int main() {
    int*    ptr_a;  // Allocate the pointers

    ptr_a = new int;    // Allocate an int pointee, and set ptr_a to point to it

    *ptr_a = 42;    // Dereference ptr_a to store 42 in its pointee
}

Shared Pointers in C

When two pointers are assigned to the same pointee, they will both point there. As a result, y points to the same pointee as x when y = x.

The pointees are unaffected by pointer assignment.

It only modifies one pointer to share the same reference as another. After the pointer assignment, the two pointers are considered “sharing” the pointee.

C code:

void main() {
    int*    ptr_a;
    int*    ptr_b;

    ptr_a = malloc(sizeof(int));

    *ptr_a = 42;

    *ptr_b = 13;    // CRASH -- ptr_b does not have a pointee yet

    ptr_b = ptr_a;      // Pointer assignment sets ptr_b to point to ptr_a's pointee

    *ptr_b = 13;    // Dereference ptr_b to store 13 in its (shared) pointee
}

We have understood the two concepts behind solving the dereferencing pointer to incomplete type error. We will now look at the codes that encounter the error and how to solve the issue.

Solve the dereferencing pointer to incomplete type Error in C

The below program has a struct rectangle with an integer member length. The name of the struct is deliberately made different than the one inside the main function to create an incomplete type.

Inside the main function, the pointer *a is created and allocated memory of the struct rectangle size, and then it is pointed towards it.

Then the pointer is used to dereference the struct member length to store a value inside it. As the struct is of incomplete type, it must throw a dereferencing pointer to incomplete type error.

#include<stdio.h>
#include<stdlib.h>

struct rectangle{
	int length;
};

int main() {
	struct square *a;
	a = (struct rectngle*)malloc(sizeof(struct rectngle));
	a->length = 33;
	printf("%d",*a);
}

Output:

1647679200/source.c: In function 'main':
1647679200/source.c:10:38: error: invalid application of 'sizeof' to incomplete type 'struct rectngle'
  a = (struct rectngle*)malloc(sizeof(struct rectngle));
                                      ^~~~~~
1647679200/source.c:11:3: error: dereferencing pointer to incomplete type 'struct square'
  a->length = 33;
   ^~

The incomplete type must be completed to resolve this issue, which in this case is the struct rectngle.

These changes must be made to complete an incomplete struct and dereference its members through a pointer inside the main function.

#include<stdio.h>
#include<stdlib.h>

struct rectangle{			// a struct rectngle is created
	int length;
};

int main() {
	struct rectangle *a;		//name of struct inside main() is same as above struct

	a = (struct rectangle*)malloc(sizeof(struct rectangle)); /*pointer allocated memory and
													  pointer to pointer 'a'.   */

    a->length = 33;									   //pointer deferenced.

	printf("%d",*a);								  //value of pointer dereferenced
}

Output:

Conclusion

This article sheds light on the error that arises due to dereferencing pointer to incomplete type. After going through this article, the reader can easily reference and deference pointers and complete incomplete types.


0

1

Как известно, с выходом OpenSSL 1.1.0 разработчики поменяли API и этим позвали всех разработчиков и хакеров в мир ошибок

ошибка: агрегатный тип <<EVP_MD_CTX mdctx>> неполон и не может быть определён
ошибка: нет декларации <<EVP_MD_CTX_cleanup>> в этой области видимости
error: invalid use of incomplete type 'DH {aka struct dh_st}'
ошибка: поле <<evp>> имеет неполный тип
ошибка: dereferencing pointer to incomplete type <<RSA {aka struct rsa_st}>>
ошибка: dereferencing pointer to incomplete type <<DSA {aka struct dsa_st}>>
ошибка: dereferencing pointer to incomplete type <<EVP_PKEY {aka struct evp_pkey_st}>>
ошибка: dereferencing pointer to incomplete type <<X509_NAME_ENTRY {aka struct X509_name_entry_st}>>
ошибка: dereferencing pointer to incomplete type <<COMP_METHOD {aka const struct comp_method_st}>>
ошибка: размер <<temp_ctx>> в памяти неизвестен
/usr/include/openssl/asn1_mac.h:10:2: ошибка: #error "This file is obsolete; please update your software."
ошибка: в макрос <<EVP_MD_CTX_create>> передано 1 аргументов, но используется только 0

и других подобных.

Конечно, изменения затронули только часть софта и остальное продолжает собираться как будто ничего и не произошло: curl, fetchmail, git, irssi, fbi,… и т.д.

А что не собирается? Например, openssh. Даже openssh-portable из git’а. libtorrent, которую использует rtorrent, тоже не собирается. nmap из тарболов не собирается, но собирается из git’а. lynx (из которого я сейчас и пишу) я пропатчил: http://saahriktu.org/downloads/patches/lynx_ssl11.patch . Ruby из тарболов тоже не собирается, но собирается из git’а. Python 2.7.12, 3.5.2 и 3.6.0a4 собираются, но с

Failed to build these modules:
_hashlib           _ssl

youtube-dl превращается в тыкву, да. Зато OpenSSL 1.1.0.

 Dereferencing pointer to incomplete type

In my header file I have:

#ifndef __STRINGTABLE__
#define __STRINGTABLE__
typedef struct StringTable *StringTable_ref;
#endif

In my main file I have:

#ifndef  __STRINGTABLE__
#define  __STRINGTABLE__
typedef struct StringTable {
       StringNode_ref   table;
       int              hsize;
       int           elements;

Quote:

#endif

StringTable_ref new_StringTable( void ) {

     StringTable_ref table1 = malloc(sizeof(StringTable_ref));
     table1->table = malloc(sizeof(StringNode_ref) * 101);
     table1->hsize = 101;
     return table1;

Quote:

And I am getting the error:
     Dereferencing pointer to incomplete type

At the lines table1->table… and table1->hsize…

I have been specifically told not to put my structures in my header
file. Any idea what I am doing wrong and what I can do?

Martien Verbrugge
#2 / 4

 Dereferencing pointer to incomplete type

On 03 Mar 2003 18:19:13 GMT,

Quote:

> In my header file I have:

> #ifndef __STRINGTABLE__
> #define __STRINGTABLE__
> typedef struct StringTable *StringTable_ref;
> #endif

That’s ok (provided you also have the prototypes for the functions
that use and operate on this type declared in here). This (public)
header file should be included by applications using your API as well
as your implementation file.

Quote:

> In my main file I have:

> #ifndef  __STRINGTABLE__
> #define  __STRINGTABLE__
> typedef struct StringTable {
>        StringNode_ref   table;
>        int              hsize;
>        int           elements;
> } StringTable_ref;
> #endif

Just do

#include «whatever_your_public_header_is_called.h»

struct StringTable {
    StringNode_ref   table;
    int              hsize;
    int           elements;

Quote:

Although I would write it as:

struct StringTable {
    struct StringTable table;
    int                hsize;
    int                elements;

Quote:

The typedef is defined in the header file, and will therefore be
available here, and the struct itself is defined here, so the rest of
your code below, in this implementation file, will be able to use it.

If you need to have access to the struct’s members in more than one
source file, consider using a «private» header file with its
definition.

Martien

                        |
Martien Verbruggen      |
Trading Post Australia  | «Mr Kaplan. Paging Mr Kaplan…»
                        |

Jack Klei
#3 / 4

 Dereferencing pointer to incomplete type

comp.lang.c.moderated:

Quote:

> In my header file I have:

> #ifndef __STRINGTABLE__
> #define __STRINGTABLE__
> typedef struct StringTable *StringTable_ref;
> #endif

This is already bad, symbols (including macros) beginning with two
underscores, or an underscore followed by an upper case letter, are
reserved for the implementation (that is, the compiler and its
headers).  Their use in your header file invokes undefined behavior.

Quote:

> In my main file I have:

> #ifndef  __STRINGTABLE__
> #define  __STRINGTABLE__

I assume, because you do not say, that in your source code file you
include the header file.  In that case, remove the #ifdef around the
definition.  The fact that you have already defined the macro causes
the compiler to skip this definition.

Quote:

> typedef struct StringTable {
>        StringNode_ref   table;
>        int              hsize;
>        int           elements;
> } StringTable_ref;
> #endif

But even if you remove the redundant include guards, you will have
another problem.  In the header file you use typedef to alias the
identifier «StringTable_ref» to a pointer to a struct StringTable.
Then in the source file you try to use typedef to alias the identifier
«StringTable_ref» to mean a struct StringTable, not a pointer to one.

In C it is illegal to typedef the same identifier more than once in a
single scope, although some compilers let it pass if the second
definition is identical to the first.  Perhaps you meant to use
StringNode_ref in the first typedef, the one in the header file?  As
it is, regardless of the incorrect include guards, you haven’t defines
the symbol «StringNode_ref» at all, anywhere.

Quote:

> StringTable_ref new_StringTable( void ) {

>      StringTable_ref table1 = malloc(sizeof(StringTable_ref));
>      table1->table = malloc(sizeof(StringNode_ref) * 101);
>      table1->hsize = 101;
>      return table1;

> }

> And I am getting the error:
>      Dereferencing pointer to incomplete type

> At the lines table1->table… and table1->hsize…

> I have been specifically told not to put my structures in my header
> file. Any idea what I am doing wrong and what I can do?

Who told you not to put structure *definitions* in a header file?  If
the structure type is to be used in more than one source file, the
definition of the structure type *absolutely* belongs in a header
file.


Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq

vis
#4 / 4

 Dereferencing pointer to incomplete type

Quote:

> In my header file I have:

> #ifndef __STRINGTABLE__
> #define __STRINGTABLE__
> typedef struct StringTable *StringTable_ref;
> #endif

> In my main file I have:

> #ifndef  __STRINGTABLE__
> #define  __STRINGTABLE__
> typedef struct StringTable {
>        StringNode_ref   table;

The real problem is here… you need to say
         StringTable_ref  table;
instead of StringNode

dereferencing pointer to incomplete type error when using typedef struct in C

Sharon

#include<stdio.h>
typedef struct data
{

    int num;
    struct node *link;
}node;
main()
{
    node *s=NULL,*e=NULL,*new;
    new=malloc(sizeof(node));
    s=malloc(sizeof(node));
    s->num=10;
    s->link=new;
    new->num=8;
    new->link=NULL;
 //  printf("%dn",s->link->num);  //// error: dereferencing pointer to incomplete type
    e=s;
    while(e!=NULL)
    {
        printf("%d",e->num);
        e=e->link;
    }

}

For the above C program I got the correct output. But if I include the commented line, it generates a dereferencing incomplete type error. Can anyone explain the reason?

Cyan

This is a naming confusion.

node == struct data thanks to typedef.

But node != struct node. They are 2 distinct types. And struct node has not been defined.

This is a pity that such a confusing construction is allowed by the C standard, and not even flagged as a warning by compilers. But that’s the way C is defined today, so we have to live with it.

My recommendation : don’t use the same names for struct and typedef. Create your own convention, for example struct thing_s and typedef struct thing_s thing_t; . This will avoid naming confusions such as this one.

The solution is now pretty obvious. Replace :

typedef struct data { int num; struct node *link; } node;

by

typedef struct data { int num; struct data *link; } node;

and the problematic printf will now work.

But your question is : why does your program worked at all without this printf ?

Now that’s an interesting one.

Let’s go back to the initial definition. As we said, struct node doesn’t exist, and is therefore incomplete. Just to better follow what we are going to explain, let’s call it struct incomplete_s instead. Now, node becomes :

typedef struct data { int num; struct incomplete_s *link; } node;

It will still work without the problematic printf.

The reason is, node is properly defined. It is a structure with known size and types. Because it doesn’t matter that struct incomplete_s is incomplete, since link is defined as a pointer to it. You could as well have defined void * link; and it would still work.

void* or struct incomplete_s * or whatever * have all same size : they are all pointers. So the structure hosting them can be properly created.

In your main loop, your program does :

   while(e!=NULL)
   {
      printf("%dn",e->num);
      e=e->link;
   }

that is e, which is a pointer node*, takes the value of e->link, which is a pointer struct incomplete_s *.

Note that both pointers are supposed to point to different types. But they are both pointers, so yeah, this assignment is technically possible and authorized by the standard.

Now a more cautious compiler would likely issue a warning here, since you are not supposed to mix pointers of different types. This is a silent type-casting, which is a recipe for future bugs. I don’t know which compiler you use, but you could increase its warning level (use «warning level 4» for Visual, or -Wall -Wextra for gcc), and it will likely not like this = operation.

A more explicit type casting would solve that (*) : e = (node*)(e->link);

Now this is no more silent, programmer is in charge, warnings will disappear.

e->link definitely exists, so compiler can grab this value. But s->link->num doesn’t exist, since s->link is struct incomplete_s*, and we don’t know what it is, so we don’t know if it has a num member.

(*) Overkill complement : At some higher optimization level, this will still be not good : strict aliasing might get in the way. So dereferencing a pointer type into another pointer type remains a dangerous operation.

Collected from the Internet

Please contact javaer1[email protected] to delete if infringement.

edited at2020-10-23

Related

Понравилась статья? Поделить с друзьями:
  • Ошибка def fan mdv
  • Ошибка depollution system faulty на citroen
  • Ошибка deep rock galactic crashed
  • Ошибка denuvo driver error code 2148204812
  • Ошибка decompression problem broken compressed data