Sorry, the question has already been asked - I did not find
Story:
I am writing a program for working with DDP, AVL-tree and hash table. And there is such a structure:

struct AVL { int value; unsigned char height; AVL *left, *right; }; 

In this form, everything works
However, if I swap fields like this: `

 struct AVL { AVL *left, *right; int value; unsigned char height; }; 

Or using #pragma pack:

 #pragma pack(push, 1) struct AVL { int value; unsigned char height; AVL *left, *right; }; #pragma pack(pop) 

That program breaks down.
In the debugger, I traced a problematic place, it is in the function of creating an AVL-tree based on the DDP:

 void bst_to_avl(BST *tree, AVL **root) { if (tree && root) { *root = avl_add(*root, tree->value); bst_to_avl(tree->left, root); bst_to_avl(tree->right, root); } } 

Here is the state in the problem function before calling avl_add:
Before calling The correct vertex is created in the avl_add function: Inside avl_add But, after exiting the function by return, it spoils and turns into this:
After the call

Naturally, the program does not work properly.
And I don’t understand a few things - how to fix it (if I, from the principle, want just such an order of fields)
And why does it even arise?
Maybe somewhere I made a very stupid mistake and now I just don’t see it.
If necessary, I can put the whole project here, but there are a lot of files
Contents BST.h

 #ifndef _BST_H_ #define _BST_H_ typedef struct BST BST; struct BST { BST *left, *right; int value; }; BST *bst_add(BST *root, int num); void bst_free(BST *root); int count_peaks(BST *root); #endif 

Link to source

  • Apparently, you are not baadf001 ... The presence of baadf001 in the memory is most likely not an accident, and as if it hints, something else happened between these two points. - AnT
  • And try printing, say, printf("%zu\n", offsetof(AVL, right)) inside avl_add and inside bst_to_avl . Do these values ​​match? - AnT
  • Chesslovo, there is a return and what is after, everything is on the screen. I can record a video :) - Rabter
  • @AnT, bst_to_avl: 16, avl_add: 8 - Rabter
  • Not sure if I used '@' correctly. I'm new here, how to? - Rabter

1 answer 1

The information provided to you in the comments (the offsetof(AVL, right) value offsetof(AVL, right) differs in different translation units) indicates that your translation units use different definitions of the struct AVL structure. It is possible that the “text” of this definition is the same, but, for example, the alignment and / or data packing installations are different in different translation units. From this follows the behavior observed to you.


I tried your code - everything works great. However, your makefile does not build complete dependencies of source files on header files. That is, when AVL.h changes, AVL.h automatically rebuilt, but not other sources that depend on AVL.h That, apparently, is your problem: you change the definition of a struct AVL , but then you only rebuild AVL.c for a new definition.

With this makefile you definitely need to do make clean after every change in the .h file and rebuild everything from scratch.

But in general, in "real" makefiles, you usually build dependency files .d using the compiler keys of the -M group. Such .d files are then included in the makefile . It is thanks to them that any changes in .h files lead to a recompilation of all .c files that depend on them.

In your case, one of the simplest solutions to the problem:

  1. Add the -MMD to the compiler command line
  2. Include .d files in makefile
  3. Delete .d files in clean

     CC := gcc CFLAGS := -std=c99 -Wall -Werror DEPFLAGS := -MMD ifeq ($(mode), debug) CFLAGS += -g3 endif -include *.d %.o: %.c %.h $(CC) $(DEPFLAGS) $(CFLAGS) -c $< app.exe: main.o io.o BST.o AVL.o bst_to_avl.o arrgen.o hash_table.o search.o restruct.o $(CC) $^ -o $@ clean: rm *.o *.d *.exe 

This option means that no one will delete the .d files separately from the .o files.

  • And how to fix it? I wonder why this is possible at all, but what to do in the case when such a nuisance occurs? Only field rearrange? - Rabter
  • @Rabter: Not, of course. Understand how and why this happened. and eliminate the difference. By the fact that you have led so far, it is difficult to say something. Are you sure that you have only one definition of a struct AVL in your program? - AnT
  • Any ideas why this could happen? It seems both use the same header ... I'll look for it anyway, of course, but if there are considerations it will help - Rabter
  • Compiler settings for each implementation file can be set separately. Because of their differences, such a sync can easily turn out, even if the same header is used. First you need to fix the variant struct AVL with which we work. And then you have in question two or three options, and in the screenshots - another one that does not coincide with any of the issue. - AnT
  • Then we take a structure without the #pragma pack, in which the first fields indicate the addresses right and left (by the way, if you spread this announcement into two lines, nothing changes) The rest, it seems, is the same all the time. So in what direction to dig, speak? - Rabter