I have a very weird problem with a piece of code I've written. I have been searching and debugging for three days now, and I still haven't found it. Unfortunately, I don't known where exactly the error is located (I know it is in area.c, but not which function etc...). So I don't really expect that you will look at it for a while, and eventually find it, but I still hope so. This is the problem :

- these are the most important structures used in the code

(coordinates are stored relatively : from 0 -> 1)

- first of all : during initialisation, this is called :Code:typedef struct Area{ struct Area *prev, *next; int handle; struct AreaEdge *top; struct AreaEdge *left; struct AreaEdge *bottom; struct AreaEdge *right; }Area; //things to know : //area1 : upper or left area //area2 : down or right area //point1 : upper or left areaPoint //point2 : down or right areaPoint typedef struct AreaEdge{ struct AreaEdge *prev, *next; struct Area *area1; struct Area *area2; struct AreaPoint *point1; struct AreaPoint *point2; int direction; }AreaEdge; #define GUI_HORIZONTAL 0 #define GUI_VERTICAL 1 typedef struct AreaPoint{ struct AreaPoint *prev, *next; float x; float y; }AreaPoint;

- situation : I have a default areaCode:addDefaultArea(s); (see last block of code)

4 areaPoints, 4 areaEdges and 1 area (linked to eachother well)

- I made a splitArea funtion which splits the area where the usere clicks with the left mouse button :

(ev->val1 and ev->val2 are the coordinates of the mouseclick)

- I'll copy area.c here.Code:case GUI_MOUSE_LEFT_DOWN: if (ae = onAreaEdge(ev->val1, ev->val2)){ splitAreaWhere(ae, ev->val1, ev->val2); return 0; } else return 1;

Now the error occurs when I have a similar situation as described here :Code://area Area *initArea(){ Area *a; a = malloc(sizeof(Area)); a->next = 0; a->prev = 0; a->top = a->bottom = a->left = a->right = 0; a->handle = 0; return a; } Area *addArea(Screen *s, AreaEdge *e1, AreaEdge *e2){ Area *a; AreaEdge *top, *left, *bottom, *right; if (!s) return 0; if (!e1 || !e2) return 0; if (e1->direction != e2->direction) return 0; a = initArea(); LIST_append(s->area, a); a->handle = (int)a; if (e1->direction == GUI_HORIZONTAL){ if(e1->point1->y > e2->point1->y){ bottom = e1; top = e2; } else{ bottom = e2; top = e1; } if ( !(left = getAreaEdge(s, top->point1, bottom->point1)) ) left = addAreaEdge(s, top->point1, bottom->point1); if ( !(right = getAreaEdge(s, top->point2, bottom->point2)) ) right = addAreaEdge(s, top->point2, bottom->point2); } else{ if(e1->point1->x > e2->point1->x){ right = e1; left = e2; } else{ right = e2; left = e1; } if ( !(top = getAreaEdge(s, left->point1, right->point1)) ) top = addAreaEdge(s, left->point1, right->point1); if ( !(bottom = getAreaEdge(s, left->point2, right->point2)) ) bottom = addAreaEdge(s, left->point2, right->point2); } a->top = top; top->area2 = a; a->left = left; left->area2 = a; a->bottom = bottom; bottom->area1 = a; a->right = right; right->area1 = a; return a; } void removeArea(Screen *s, Area *a){ int index; index = LIST_getElemIndex(s->area, a); LIST_removeAt(s->area, index); if (a == a->top->area2) a->top->area2 = 0; if (a == a->bottom->area1) a->bottom->area1 = 0; if (a == a->left->area2) a->left->area2 = 0; if (a == a->right->area1) a->right->area1 = 0; a->handle = 0; freeArea(a); } void freeAreaList(List *l){ Area *a; while(l->first){ a = LIST_removeLast(l); freeArea(a); } } void freeArea(Area *a){ free(a); } //areaEdge AreaEdge *initAreaEdge(){ AreaEdge *ae; ae = malloc(sizeof(AreaEdge)); ae->next = 0; ae->prev = 0; ae->point1 = 0; ae->point2 = 0; ae->area1 = 0; ae->area2 = 0; ae->direction = -1; return ae; } AreaEdge *addAreaEdge(Screen *s, AreaPoint *p1, AreaPoint *p2){ AreaEdge *a; int dir=0; if (!s) return 0; if (!p1 || !p2) return 0; if ( (p2->x - p1->x) > 0.0001f ) dir |= 1; if ( (p2->y - p1->y) > 0.0001f ) dir |= 2; if (dir == 0 || dir == 3) return 0; dir--; a = initAreaEdge(); LIST_append(s->areaEdge, a); a->point1 = p1; a->point2 = p2; a->direction = dir; return a; } void removeAreaEdge(Screen *s, AreaEdge *ae){ int index; if (ae->area1 || ae->area2) return; index = LIST_getElemIndex(s->areaEdge, ae); LIST_removeAt(s->areaEdge, index); ae->point1 = 0; ae->point2 = 0; ae->direction = -1; freeAreaEdge(ae); } void freeAreaEdgeList(List *l){ AreaEdge *ae; while(l->first){ ae = LIST_removeLast(l); freeAreaEdge(ae); } } void freeAreaEdge(AreaEdge *ae){ free(ae); } AreaEdge *getAreaEdge(Screen *s, AreaPoint *p1, AreaPoint *p2){ AreaEdge *t; t = s->areaEdge->first; while(t){ if (t->point1 == p1 && t->point2 == p2){ return t; } else if (t->point1 == p2 && t->point2 == p1){ return t; } t = t->next; } return 0; } //areaPoint AreaPoint *initAreaPoint(){ AreaPoint *ap; ap = malloc(sizeof(AreaPoint)); ap->next = 0; ap->prev = 0; ap->x = 0; ap->y = 0; return ap; } AreaPoint *addAreaPoint(Screen *s, float x, float y){ AreaPoint *p; if (!s) return 0; p = initAreaPoint(); LIST_append(s->areaPoint, p); p->x = x; p->y = y; return p; } void removeAreaPoint(Screen *s, AreaPoint *ap){ AreaEdge *t; int index; t = s->areaEdge->first; while(t){ if (t->point1 == ap || t->point2 == ap) return; t = t->next; } index = LIST_getElemIndex(s->areaPoint, ap); LIST_removeAt(s->areaPoint, index); ap->x = 0; ap->y = 0; freeAreaPoint(ap); } void freeAreaPointList(List *l){ AreaPoint *ae; while(l->first){ ae = LIST_removeLast(l); freeAreaPoint(ae); } } void freeAreaPoint(AreaPoint *ap){ free(ap); } void addDefaultArea(Screen *s){ AreaPoint *p1, *p2, *p3, *p4; AreaEdge *e1, *e2, *e3, *e4; Area *a; float x, y; x = 0; y = 0; p1 = addAreaPoint(s, x, y); x = 1; y = 0; p2 = addAreaPoint(s, x, y); x = 1; y = 1; p3 = addAreaPoint(s, x, y); x = 0; y = 1; p4 = addAreaPoint(s, x, y); e1 = addAreaEdge(s, p1, p2); e2 = addAreaEdge(s, p2, p3); e3 = addAreaEdge(s, p4, p3); e4 = addAreaEdge(s, p1, p4); a = addArea(s, e1, e3); } void splitAreaWhere(AreaEdge *ae, int x, int y){ AreaPoint *lb, *rb, *ro, *lo, *newp1, *newp2; AreaEdge *b, *o, *l, *r, *newe1, *newe2, *newe3, *newe4, *newe5; Area *split = 0, *newa1, *newa2; guiEvent *event = 0; float fx, fy, where; int dir, loop_done = 0; //1 : omzetten naar relatieve coordinaten fx = (float)x / (float)G->win->x; fy = (float)y / (float)G->win->y; dir = ae->direction; //2 : berekenen welke area if (dir == GUI_HORIZONTAL){ where = fx; if (fy >= ae->point1->y) split = ae->area2; else split = ae->area1; } else{ where = fy; if (fx >= ae->point1->x) split = ae->area2; else split = ae->area1; } printf("split : %d\n", split); printf("ae : %d\n", ae); lb = split->top->point1; rb = split->top->point2; ro = split->bottom->point2; lo = split->bottom->point1; b = split->top; o = split->bottom; l = split->left; r = split->right; //3 : de eigenlijke splitsing if (dir == GUI_HORIZONTAL){ removeArea(G->curScreen, split); removeAreaEdge(G->curScreen, b); removeAreaEdge(G->curScreen, o); newp1 = addAreaPoint(G->curScreen, where, l->point1->y); newp2 = addAreaPoint(G->curScreen, where, l->point2->y); newe1 = addAreaEdge(G->curScreen, lb, newp1); newe2 = addAreaEdge(G->curScreen, newp1, rb); newe3 = addAreaEdge(G->curScreen, lo, newp2); newe4 = addAreaEdge(G->curScreen, newp2, ro); newe5 = addAreaEdge(G->curScreen, newp1, newp2); newa1 = addArea(G->curScreen, newe1, newe3); newa2 = addArea(G->curScreen, newe2, newe4); } else{ removeArea(G->curScreen, split); removeAreaEdge(G->curScreen, l); removeAreaEdge(G->curScreen, r); newp1 = addAreaPoint(G->curScreen, b->point1->x, where); newp2 = addAreaPoint(G->curScreen, b->point2->x, where); newe1 = addAreaEdge(G->curScreen, lb, newp1); newe2 = addAreaEdge(G->curScreen, newp1, lo); newe3 = addAreaEdge(G->curScreen, rb, newp2); newe4 = addAreaEdge(G->curScreen, newp2, ro); newe5 = addAreaEdge(G->curScreen, newp1, newp2); newa1 = addArea(G->curScreen, newe1, newe3); newa2 = addArea(G->curScreen, newe2, newe4); } /*//4 : in loop gaan tot key-up while (!loop_done){ loop_done = 1; } //5 : aanpassen van vensterdata //6 : update()*/ /*printf("areas :\n"); LIST_printList(G->curScreen->area); printf("areaEdges :\n"); LIST_printList(G->curScreen->areaEdge); printf("areaPoints :\n"); LIST_printList(G->curScreen->areaPoint); printf("\n");*/ } void joinAreas(AreaEdge *ae){ } AreaEdge *onAreaEdge(int x, int y){ AreaEdge *a; float fx, fy; float t, b, l, r; float offs = 0.01f; fx = (float)x / (float)G->win->x; fy = (float)y / (float)G->win->y; a = G->curScreen->areaEdge->first; while (a){ t = a->point1->y - offs; b = a->point2->y + offs; l = a->point1->x - offs; r = a->point2->x + offs; if (t<=fy && b>=fy && l<=fx && r>=fx) return a; a = a->next; } return 0; }

This is ofcourse flippable.Code:1) ------------------ | | | | | | | | | | | | | | ------------------ 2) ------------------ | | | | | | | | | | | | | | | | | | | | | ------------------ 3) ------------------ | | | | | | | |------| | | | | | | | | | | | | ------------------ 4) ------------------ | | | | | | | |------| | | | | |------| | | | | | | ------------------

The problem happens inbetween situation 3 and 4, when I have called splitAreaWhere(). It crashes at this line :

lb = split->top->point1;

Debugging showed me that split didn't get a value. That is because in the next block, ae->area2 == 0. And this is wrong since ae->area2 shouldn't be NULL.

I hope someone has a clue. If this is not clear, or if someone should be interested in this problem, then the complete source can be found here :Code:else{ where = fy; if (fx >= ae->point1->x) split = ae->area2; else split = ae->area1; }

http://users.pandora.be/willem.packet1/Gui.zip

Thanks in advance,

Hans