Beginner of studying Graph in ADT, C language.
This is the code that debug had captured. The debugging result is plist->cur was 0xCDCDCDCD.(from DLinkedList.c)
And Debug program said that upper code occurs error on these call sequences.
ConKruskalMST(&graph);(main code)
if (!IsConnVertex(pg, edge.v1, edge.v2));(ALGraphKruskal.c, line 172)
while (LNext(&(pg->adjList[visitV]), &nextV) == TRUE); (ALGraphKruskal.c,
line 108)
*cur -> 0xCDCDCDCD{data = ?? next = ??} can't read memory of data, next
I couldn't understand why this was the error.
Would you help me to find the problem on this code? It will be very helpful for me. Total codes for Kruskal are under this line.
Thank you
P.S. These codes are in the book named "Introduction to Data Structures Using C for studying ADT".
Filename-> ALEdge.h / ALGraphKruskal.h / ArrayBaseStack.h / DLinkedList.h / PriorityQueue.h / UsefulHeap.h / ALGraphKruskal.c / ArrayBaseStack.c / DLinkedList.c / KruskalMain.c / PriorityQueue.c / UsefulHeap.c
[ALEdge.h]
#ifndef __AL_EDGE__
#define __AL_EDGE__
typedef struct _edge {
int v1;
int v2;
int weight;
} Edge;
#endif
[ALGraphKruskal.h]
#ifndef __AL_GRAPH_KRUSKAL__
#define __AL_GRAPH_KRUSKAL__
#include "DLinkedList.h"
#include "PriorityQueue.h"
#include "ALEdge.h"
#include "ArrayBaseStack.h"
enum { A, B, C, D, E, F, G, H, I, J };
typedef struct _ual {
int numV;
int numE;
List * adjList;
int * visitInfo;
PQueue pqueue;
} ALGraph;
void GraphInit(ALGraph * pg, int nv);
void GraphDestroy(ALGraph * pg);
void AddEdge(ALGraph * pg, int fromV, int toV, int weight);
void ShowGraphEdgeInfo(ALGraph * pg);
int IsConnVertex(ALGraph * pg, int v1, int v2);
void ConKruskalMST(ALGraph * pg);
void ShowGraphEdgeWeightInfo(ALGraph * pg);
#endif
[ArrayBaseStack.h]
#ifndef __AB_STACK_H__
#define __AB_STACK_H__
#define TRUE 1
#define FALSE 0
#define STACK_LEN 100
typedef int Data;
typedef struct _arrayStack {
Data stackArr[STACK_LEN];
int topIndex;
} ArrayStack;
typedef ArrayStack Stack;
void StackInit(Stack * pstack);
int SIsEmpty(Stack * pstack);
void SPush(Stack * pstack, Data data);
Data SPop(Stack * pstack);
Data SPeek(Stack * pstack);
#endif
[DLinkedList.h]
#ifndef __D_LINKED_LIST_H__
#define __D_LINKED_LIST_H__
#define TRUE 1
#define FALSE 0
typedef int LData;
typedef struct _node {
LData data;
struct _node * next;
} Node;
typedef struct _linkedList {
Node * head;
Node * cur;
Node * before;
int numOfData;
int(*comp)(LData d1, LData d2);
} LinkedList;
typedef LinkedList List;
void ListInit(List * plist);
void LInsert(List * plist, LData data);
int LFirst(List * plist, LData * pdata);
int LNext(List * plist, LData * pdata);
LData LRemove(List * plist);
int LCount(List * plist);
void SetSortRule(List * plist, int(*comp)(LData d1, LData d2));
#endif
[PriorityQueue.h]
#ifndef __PRIORITY_QUEUE_H__
#define __PRIORITY_QUEUE_H__
#include "UsefulHeap.h"
typedef Heap PQueue;
typedef HData PQData;
void PQueueInit(PQueue * ppq, PriorityComp pc);
int PQIsEmpty(PQueue * ppq);
void PEnqueue(PQueue * ppq, PQData data);
PQData PDequeue(PQueue * ppq);
#endif __PRIORITY_QUEUE_H__
[UsefulHeap.h]
#ifndef __USEFUL_HEAP_H__
#define __USEFUL_HEAP_H__
#define TRUE 1
#define FALSE 0
#define HEAP_LEN 100
#include "ALEdge.h"
typedef Edge HData;
typedef int PriorityComp(HData d1, HData d2);
typedef struct _heap {
PriorityComp * comp;
int numOfData;
HData heapArr[HEAP_LEN];
} Heap;
void HeapInit(Heap * ph, PriorityComp pc);
int HIsEmpty(Heap * ph);
void HInsert(Heap * ph, HData data);
HData HDelete(Heap * ph);
#endif
[ALGraphKruskal.c]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ALGraphKruskal.h"
#include "DLinkedList.h"
int WhoIsPrecede(int data1, int data2);
int PQWeightComp(Edge d1, Edge d2);
int PQWeightComp(Edge d1, Edge d2) {
return d1.weight - d2.weight;
}
void GraphInit(ALGraph * pg, int nv) {
int i;
pg->adjList = (List*)malloc(sizeof(List) * nv);
pg->numV = nv;
pg->numE = 0;
for (i = 0; i < nv; i++) {
ListInit(&(pg->adjList[i]));
SetSortRule(&(pg->adjList[i]), WhoIsPrecede);
}
pg->visitInfo = (int*)malloc(sizeof(int) * pg->numV);
memset(pg->visitInfo, 0, sizeof(int) * pg->numV);
PQueueInit(&(pg->pqueue), PQWeightComp);
}
void GraphDestroy(ALGraph * pg) {
if (pg->adjList != NULL)
free(pg->adjList);
if (pg->visitInfo != NULL);
free(pg->visitInfo);
}
void AddEdge(ALGraph * pg, int fromV, int toV, int weight) {
Edge edge = { fromV, toV, weight };
LInsert(&(pg->adjList[fromV]), toV);
LInsert(&(pg->adjList[toV]), fromV);
pg->numE += 1;
PEnqueue(&(pg->pqueue), edge);
}
void ShowGraphEdgeInfo(ALGraph * pg) {
int i;
int vx;
for (i = 0; i < pg->numV; i++) {
printf("%c connects with: ", i + 65);
if (LFirst(&(pg->adjList[i]), &vx)) {
printf("%c ", vx + 65);
while (LNext(&(pg->adjList[i]), &vx))
printf("%c ", vx + 65);
}
printf("\n");
}
}
int WhoIsPrecede(int data1, int data2) {
if (data1 < data2)
return 0;
else
return 1;
}
int VisitVertex(ALGraph * pg, int visitV) {
if (pg->visitInfo[visitV] == 0) {
pg->visitInfo[visitV] = 1;
printf("%c ", visitV + 65);
return TRUE;
}
return FALSE;
}
int IsConnVertex(ALGraph * pg, int v1, int v2) {
Stack stack;
int visitV = v1;
int nextV;
StackInit(&stack);
VisitVertex(pg, visitV);
SPush(&stack, visitV);
while (LFirst(&(pg->adjList[visitV]), &nextV) == TRUE) {
int visitFlag = FALSE;
if (nextV == v2) {
memset(pg->visitInfo, 0, sizeof(int) * pg->numV);
return TRUE;
}
if (VisitVertex(pg, nextV) == TRUE) {
SPush(&stack, visitV);
visitV = nextV;
visitFlag = TRUE;
}
else {
while (LNext(&(pg->adjList[visitV]), &nextV) == TRUE) {
if (nextV == v2) {
memset(pg->visitInfo, 0, sizeof(int) * pg->numV);
return TRUE;
}
if (VisitVertex(pg, nextV) == TRUE) {
SPush(&stack, visitV);
visitV = nextV;
visitFlag = TRUE;
}
}
}
if (visitFlag == FALSE) {
if (SIsEmpty(&stack) == TRUE)
break;
else
visitV = SPop(&stack);
}
}
memset(pg->visitInfo, 0, sizeof(int) * pg->numV);
return FALSE;
}
void RemoveWayEdge(ALGraph * pg, int fromV, int toV) {
int edge;
if (LFirst(&(pg->adjList[fromV]), &edge)) {
if (edge == toV) {
LRemove(&(pg->adjList[fromV]));
return;
}
while (LNext(&(pg->adjList[fromV]), &edge)) {
if (edge == toV) {
LRemove(&(pg->adjList[fromV]));
return;
}
}
}
}
void RemoveEdge(ALGraph * pg, int fromV, int toV) {
RemoveWayEdge(pg, fromV, toV);
RemoveWayEdge(pg, toV, fromV);
(pg->numE)--;
}
void RecoverEdge(ALGraph * pg, int fromV, int toV, int weight) {
LInsert(&(pg->adjList[fromV]), toV);
LInsert(&(pg->adjList[toV]), fromV);
(pg->numE)--;
}
void ConKruskalMST(ALGraph * pg) {
Edge recvEdge[20];
Edge edge;
int eidx = 0;
int i;
while (pg->numE + 1 > pg->numV) {
edge = PDequeue(&(pg->pqueue));
RemoveEdge(pg, edge.v1, edge.v2);
if (!IsConnVertex(pg, edge.v1, edge.v2)) {
RecoverEdge(pg, edge.v1, edge.v2, edge.weight);
recvEdge[eidx++] = edge;
}
}
for (i = 0; i < eidx; i++) {
PEnqueue(&(pg->pqueue), recvEdge[i]);
}
}
void ShowGraphEdgeWeightInfo(ALGraph * pg) {
PQueue copyPQ = pg->pqueue;
Edge edge;
while (!PQIsEmpty(©PQ)) {
edge = PDequeue(©PQ);
printf("(%c-%c), w:%d \n", edge.v1 + 65, edge.v2 + 65, edge.weight);
}
}
[ArrayBaseStack.c]
#include <stdio.h>
#include <stdlib.h>
#include "ArrayBaseStack.h"
void StackInit(Stack * pstack) {
pstack->topIndex = -1;
}
int SIsEmpty(Stack * pstack) {
if (pstack->topIndex == -1)
return TRUE;
else
return FALSE;
}
void SPush(Stack * pstack, Data data) {
pstack->topIndex += 1;
pstack->stackArr[pstack->topIndex] = data;
}
Data SPop(Stack * pstack) {
int rIdx;
if (SIsEmpty(pstack)) {
printf("Error! \n");
exit(-1);
}
rIdx = pstack->topIndex;
pstack->topIndex -= 1;
return pstack->stackArr[rIdx];
}
Data SPeek(Stack * pstack) {
if (SIsEmpty(pstack)) {
printf("Error! \n");
exit(-1);
}
return pstack->stackArr[pstack->topIndex];
}
[DLinkedList.c]
#include <stdio.h>
#include <stdlib.h>
#include "DLinkedList.h"
void ListInit(List * plist) {
plist->head = (Node*)malloc(sizeof(Node));
plist->head->next = NULL;
plist->comp = NULL;
plist->numOfData = 0;
}
void FInsert(List * plist, LData data) {
Node * newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = plist->head->next;
plist->head->next = newNode;
(plist->numOfData)++;
}
void SInsert(List * plist, LData data) {
Node * newNode = (Node*)malloc(sizeof(Node));
Node * pred = plist->head;
newNode->data = data;
while (pred->next != NULL && plist->comp(data, pred->next->data) != 0) {
pred = pred->next;
}
newNode->next = pred->next;
pred->next = newNode;
(plist->numOfData)++;
}
void LInsert(List * plist, LData data) {
if (plist->comp == NULL)
FInsert(plist, data);
else
SInsert(plist, data);
}
int LFirst(List * plist, LData * pdata) {
if (plist->head->next == NULL)
return FALSE;
plist->before = plist->head;
plist->cur = plist->head->next;
*pdata = plist->cur->data;
return TRUE;
}
int LNext(List * plist, LData * pdata) {
if(plist->cur->next == NULL)
return FALSE;
plist->before = plist->cur;
plist->cur = plist->cur->next;
*pdata = plist->cur->data;
return TRUE;
}
LData LRemove(List * plist) {
Node * rpos = plist->cur;
LData rdata = rpos->data;
plist->before->next = plist->cur->next;
plist->cur = plist->before;
free(rpos);
(plist->numOfData)--;
return rdata;
}
int LCount(List * plist) {
return plist->numOfData;
}
void SetSortRule(List * plist, int(*comp)(LData d1, LData d2)) {
plist->comp = comp;
}
[KruskalMain.c]
#include <stdio.h>
#include "ALGraphKruskal.h"
int main(void) {
ALGraph graph;
GraphInit(&graph, 6);
AddEdge(&graph, A, B, 9);
AddEdge(&graph, B, C, 2);
AddEdge(&graph, A, C, 12);
AddEdge(&graph, A, D, 8);
AddEdge(&graph, D, C, 6);
AddEdge(&graph, A, F, 11);
AddEdge(&graph, F, D, 4);
AddEdge(&graph, D, E, 3);
AddEdge(&graph, E, C, 7);
AddEdge(&graph, F, E, 13);
ConKruskalMST(&graph);
ShowGraphEdgeInfo(&graph);
ShowGraphEdgeWeightInfo(&graph);
GraphDestroy(&graph);
return 0;
}
[PriorityQueue.c]
#include "PriorityQueue.h"
#include "UsefulHeap.h"
void PQueueInit(PQueue * ppq, PriorityComp pc) {
HeapInit(ppq, pc);
}
int PQIsEmpty(PQueue * ppq) {
return HIsEmpty(ppq);
}
void PEnqueue(PQueue * ppq, PQData data) {
HInsert(ppq, data);
}
PQData PDequeue(PQueue * ppq) {
return HDelete(ppq);
}
[UsefulHeap.c]
#include "UsefulHeap.h"
void HeapInit(Heap * ph, PriorityComp pc) {
ph->numOfData = 0;
ph->comp = pc;
}
int HIsEmpty(Heap * ph) {
if (ph->numOfData == 0)
return TRUE;
else
return FALSE;
}
int GetParentIDX(int idx) {
return idx / 2;
}
int GetLChildIDX(int idx) {
return idx * 2;
}
int GetRChildIDX(int idx) {
return GetLChildIDX(idx) + 1;
}
int GetHiPriChildIDX(Heap * ph, int idx) {
if (GetLChildIDX(idx) > ph->numOfData)
return 0;
else if (GetLChildIDX(idx) == ph->numOfData)
return GetLChildIDX(idx);
else {
if (ph->comp(ph->heapArr[GetLChildIDX(idx)], ph->heapArr[GetRChildIDX(idx)]) < 0)
return GetRChildIDX(idx);
else
return GetLChildIDX(idx);
}
}
void HInsert(Heap * ph, HData data) {
int idx = ph->numOfData + 1;
while (idx != 1) {
if (ph->comp(data, ph->heapArr[GetParentIDX(idx)]) > 0) {
ph->heapArr[idx] = ph->heapArr[GetParentIDX(idx)];
idx = GetParentIDX(idx);
}
else
break;
}
ph->heapArr[idx] = data;
ph->numOfData += 1;
}
HData HDelete(Heap * ph) {
HData retData = ph->heapArr[1];
HData lastElem = ph->heapArr[ph->numOfData];
int parentIdx = 1;
int childIdx;
while (childIdx = GetHiPriChildIDX(ph, parentIdx)) {
if (ph->comp(lastElem, ph->heapArr[childIdx]) >= 0)
break;
ph->heapArr[parentIdx] = ph->heapArr[childIdx];
parentIdx = childIdx;
}
ph->heapArr[parentIdx] = lastElem;
ph->numOfData -= 1;
return retData;
}
In DLinkedList.c
int LNext(List * plist, LData * pdata) {
if(plist->cur->next == NULL)
return FALSE;
plist->before = plist->cur;
plist->cur = plist->cur->next;
*pdata = plist->cur->data;
return TRUE;
}
The case where plist->cur is NULL is missed so. if you change the code to:
int LNext(List * plist, LData * pdata) {
if(plist->cur == NULL)
return FALSE;
if(plist->cur->next == NULL)
return FALSE;
plist->before = plist->cur;
plist->cur = plist->cur->next;
*pdata = plist->cur->data;
return TRUE;
}
It should work fine.
Related
Good evening forum members.
The following is on the agenda:
Read a sequence of coordinates (x, y, z) of spatial points from the file, ordered by distance from the point of origin (develop a separate function for calculating the distance and store this value in the data structure);
To bypass use the bottom option from right to left;
Extract from the tree all nodes whose z coordinate falls within the specified range zmin ..zmax (I decided to take from 7 to 14) and indicate their number;
To completely erase the tree, use the direct (from the root) version of the bypass from left to right;
Print the entire tree using a non-recursive function.
Please help with number 3. It is not possible to implement the deletion algorithm according to a given condition. It either does not work at all, or errors arrive (
Thanks in advance to everyone who responds
CODE:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX_LEN 8
#define STACK_INIT_SIZE 20
typedef struct Tree {
int z;
int viddal;
struct Tree* left, * right;
} TREE;
typedef struct Stack {
size_t size, limit;
TREE** data;
} STACK;
int Distance(FILE* ftxt, int* vid, int* z_cord);
int CreateTreeFromFile(void);
TREE* NewNode(FILE* f, int viddal, int z);
void AddNewNode(TREE* pnew);
void PrintTreeNIZ(TREE* proot);
void iterPostorder(TREE* root);
void OutputTreeStructure(const char* title);
void ShowTree(TREE* proot, int level);
void ShowLevels(void);
int TreeHeight(TREE* proot);
void EraseTree(TREE* proot);
void DeleteSomeNodes(void);
int DeleteNode(TREE* pnew_adr);
TREE* root;
int main(){
system("chcp 1251");
if (CreateTreeFromFile() == 0)
return 0;
puts("\n Created tree: ");
PrintTreeNIZ(root);
OutputTreeStructure("of created tree");
DeleteSomeNodes();
OutputTreeStructure("of the new tree");
EraseTree(root);
root = NULL;
puts("\n Tree was deleted from DM\n\n");
return 0;
}
int Distance(FILE* ftxt, int *vid, int* z_cord) {
TREE* pel = (TREE*)malloc(sizeof(TREE));
if (feof(ftxt)) {;
return NULL;
}
else {
int x, y, z;
fscanf(ftxt, "%d%d%d", &x, &y, &z);
*z_cord = z;
*vid = sqrt(x * x + y * y + z * z);
}
}
int CreateTreeFromFile()
{
const char* fname = "Cords_1.txt";
FILE* fvoc = fopen(fname, "r");
if (fvoc == NULL) {
printf("\n\t\tCan`t open file %s...\n", fname);
return 0;
}
TREE* node;
int viddal, z;
Distance(fvoc, &viddal, &z);
while ((node = NewNode(fvoc, viddal, z)) != NULL) {
AddNewNode(node);
Distance(fvoc, &viddal, &z);
}
fclose(fvoc);
return 1;
}
TREE* NewNode(FILE* f, int viddal, int z)
{
TREE* pel;
pel = (TREE*)malloc(sizeof(TREE));
if (feof(f)) {
return NULL;
}
pel->viddal = viddal;
pel->z = z;
pel->left = pel->right = NULL;
return pel;
}
void AddNewNode(TREE* pnew) {
if (root == NULL) {
root = pnew;
return;
}
TREE* prnt = root;
do {
if (pnew->viddal == prnt->viddal) {
free(pnew);
return;
}
if (pnew->viddal < prnt->viddal) {
if (prnt->left == NULL) {
prnt->left = pnew;
return;
}
else
prnt = prnt->left;
}
else {
if (prnt->right == NULL) {
prnt->right = pnew;
return;
}
else
prnt = prnt->right;
}
} while (1);
}
void PrintTreeNIZ(TREE* proot)
{
if (proot == NULL)
return;
printf("\n Right Tree");
iterPostorder(proot->right);
printf("\n\n Left Tree");
iterPostorder(proot->left);
printf("\n\n Korin - %d", proot->viddal);
}
void OutputTreeStructure(const char* title)
{
printf("\n\n\n Structur%s:\n\n", title);
ShowLevels();
ShowTree(root, 0);
puts("\n");
}
#define TAB 7
void ShowTree(TREE* proot, int level)
{
if (proot == NULL) return;
ShowTree(proot->right, level + 1);
printf("\n%*c%d", level * TAB + 10, ' ', proot->viddal);
ShowTree(proot->left, level + 1);
}
void ShowLevels(void)
{
int lev;
printf(" Level: ");
for (lev = 1; lev <= TreeHeight(root); lev++)
printf(" %-*d", 6, lev);
printf("\n\n");
}
int TreeHeight(TREE* proot)
{
int lh, rh;
if (proot == NULL) return 0;
lh = TreeHeight(proot->left);
rh = TreeHeight(proot->right);
return lh > rh ? lh + 1 : rh + 1;
}
void EraseTree(TREE* proot)
{
if (proot == NULL)
return;
EraseTree(proot->left);
EraseTree(proot->right);
free(proot);
}
STACK* createStack() {
Stack* tmp = (Stack*)malloc(sizeof(Stack));
tmp->limit = STACK_INIT_SIZE;
tmp->size = 0;
tmp->data = (TREE**)malloc(tmp->limit * sizeof(TREE*));
return tmp;
}
void freeStack(Stack** s) {
free((*s)->data);
free(*s);
*s = NULL;
}
void push(Stack* s, TREE* item) {
if (s->size >= s->limit) {
s->limit *= 2;
s->data = (TREE**)realloc(s->data, s->limit * sizeof(TREE*));
}
s->data[s->size++] = item;
}
TREE* pop(Stack* s) {
if (s->size == 0) {
exit(7);
}
s->size--;
return s->data[s->size];
}
TREE* peek(Stack* s) {
return s->data[s->size - 1];
}
void iterPostorder(TREE* root) {
Stack* ps = createStack();
TREE* lnp = NULL;
TREE* peekn = NULL;
while (!ps->size == 0 || root != NULL) {
if (root) {
push(ps, root);
root = root->left;
}
else {
peekn = peek(ps);
if (peekn->right && lnp != peekn->right) {
root = peekn->right;
}
else {
pop(ps);
printf("\n\t Visited -> %d", peekn->viddal);
lnp = peekn;
}
}
}
freeStack(&ps);
}
// HELP WITH THAT
//--------------------------------------------------------------------------------------------
void DeleteSomeNodes(void)
{
printf("\n\t Deleting needing nods:\n");
TREE* pfind = (TREE*)malloc(sizeof(TREE));
do {
if (pfind->z >= 7 && pfind->z <= 14) {
DeleteNode(root);
printf(" Number %d was deleted from tree\n", root);
}
} while (1);
puts("\n\n");
}
#define NoSubTree 0
#define LeftSubTree -1
#define RightSubTree 1
#define TwoSubTrees 2
int DeleteNode(TREE* pnew_adr)
{
TREE* proot = root;
int subtr;
if (proot == NULL) return 0;
if (pnew_adr->viddal < proot->viddal)
return DeleteNode(proot->left);
if (pnew_adr->viddal > proot->viddal)
return DeleteNode(proot->right);
if (proot->left == NULL && proot->right == NULL)
subtr = NoSubTree;
else if (proot->left == NULL)
subtr = RightSubTree;
else if (proot->right == NULL)
subtr = LeftSubTree;
else
subtr = TwoSubTrees;
switch (subtr) {
case NoSubTree:
root = NULL; break;
case LeftSubTree:
root = proot->left; break;
case RightSubTree:
root = proot->right; break;
case TwoSubTrees:
TREE* pnew_root = proot->right, * pnew_prnt = proot;
while (pnew_root->left != NULL) {
pnew_prnt = pnew_root;
pnew_root = pnew_root->left;
}
pnew_root->left = proot->left;
if (pnew_root != proot->right) {
pnew_prnt->left = pnew_root->right;
pnew_root->right = proot->right;
}
root = pnew_root;
}
free(proot);
return 1;
}
//--------------------------------------------------------------------------------------------
I am coding a hash table with singly linkedList and I have this problem free(): double free detected in tcache 2 I tried to fix it but did'nt make it, the problem its the free() , so could you explain me why I have it, So if anyone can help, so please help me, I'm trying to fix it for hours now...
Thank you.
I've watched some video on youtube and many topics on websitte and also here but I didn't find a solution for mine.
This are my functions:
/**List header */
#ifndef LISTE_H
#define LISTE_H
struct _list_node {
void * data;
struct _list_node *next;
};
typedef struct _list_node s_node;
s_node * list_create(void);
void * list_get_data(s_node * node);
void list_set_data(s_node * node, void * data);
s_node * list_insert(s_node * head, void * data);
s_node * list_append(s_node * head, void * data);
int list_process(s_node * head, int (*fct)(s_node * node, void * param),
void * param, s_node ** last);
s_node * list_ordered_append(s_node ** head, int (*fct)(s_node * node, void * param),
void * param);
s_node * list_remove (s_node * head, void * data);
s_node * list_headRemove(s_node * head);
void * list_destroy(s_node * head);
void afficher_s_node(s_node * list);
int list_is_empty( s_node * node );
unsigned int list_size(s_node * node);
int list_process(s_node * head, int (*fct)(s_node * node, void * param),
void * param, s_node ** last);
#endif
/**** c file list */
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
s_node * list_create(void)
{
return NULL;
}
void * list_get_data(s_node * node)
{
return node->data;
}
void list_set_data(s_node * node, void * data)
{
node->data = data;
}
s_node * list_insert(s_node * head, void * data)
{
s_node * node = (s_node *) malloc(sizeof(s_node));
list_set_data(node, data);
node->next = head;
return node;
}
s_node * list_append(s_node * head, void * data)
{
if (!head) return list_insert(head, data);
s_node * node = head;
while (node->next) {
node = node->next;
}
node->next = (s_node *) malloc(sizeof(s_node));
node->next->next = list_create();
list_set_data(node->next, data);
return head;
}
int list_process(s_node * head, int (*fct)(s_node * node, void * param),
void * param, s_node ** last)
{
if (!head) return 0;
s_node * node;
for (node = head; node; node = node->next) {
if (fct(node, param) == 1) {
*last = node;
return 1;
}
}
return 0;
}
s_node * list_ordered_append(s_node ** head, int (*fct)(s_node * node, void * param),
void * param)
{
// quand elle est vide
if (!(*head)) {
*head = list_insert(*head, param);
return *head;
}
// insertion en tete
s_node * node;
if (fct(*head, param) == 1) {
*head = list_insert(*head, param);
return (*head);
}
// cas general
int res;
for(node = *head; node->next; node = node->next) {
if ((res = fct(node->next, param)) == 1) {
node->next = list_insert(node->next, param);
return node->next;
} else if (res == 0) {
return node->next;
}
}
if (fct(node, param) == 0) return node;
*head = list_append(*head, param);
return node->next;
}
s_node * list_remove (s_node * head, void * data)
{
if (!head) return head;
for (s_node * node = head; node->next; node = node->next) {
if (node->next->data == data) {
s_node * n = node->next->next;
free(node->next);
node->next = n;
break;
}
}
return head;
}
s_node * list_headRemove(s_node * head)
{
if (!head) return head;
s_node * n = head->next;
free(head);
return n;
}
void * list_destroy(s_node * head)
{
while (head)
head = list_headRemove(head);
}
void afficher_s_node(s_node * list)
{
printf("\nliste = [");
while (list) {
printf("%d,", *((int *)(list->data)));
list = list->next;
}
printf("]\n");
return;
}
int list_is_empty( s_node * node ) {
return NULL == node;
}
unsigned int list_size(s_node * node)
{
unsigned int i = 0;
while (node) {
node = node->next;
i++;
}
return i;
}
/*PLUS
int list_process(s_node * head, int (*fct)(s_node * node, void * param),
void * param, s_node ** last)
{
if (!head) return 0;
s_node * node;
for (node = head; node; node = node->next) {
if (fct(node, param) == 1) {
*last = node;
return 1;
}
}
return 0;
}
*/
/* hash table header */
#ifndef HACHAGE_H
#define HACHAGE_H
#include "list.h"
typedef struct {
s_node * node;
unsigned int len;
} super_list;
typedef struct {
super_list * list;
unsigned int len;
} strhash_table;
strhash_table * strhash_table_init(const unsigned int len);
strhash_table * strhash_table_destroy(strhash_table * table);
strhash_table * strhash_table_free(strhash_table * table);
char * strhash_table_add(strhash_table * table, char * str);
strhash_table * strhash_table_remove(strhash_table * table, char * str);
void strhash_table_info(strhash_table * table);
void strhash_print(strhash_table * table);
#endif
/**** c file hash table */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "hachage.h"
#include "list.h"
int hashCode(char * str, const int size_hash_table)
{
int i, cle = 0;
for (i = 0; str[i] != '\0'; i++) {
cle *= 2;
cle += (int) str[i];
}
return cle % size_hash_table;
}
int compare_str_add(s_node *node, void *param)
{
int res = strcmp((char *) node->data, (char *) param);
/*if the first non-matching character in node->data
is lower (in ASCII) than that of param.*/
if (res < 0) return -1;
/*if the first non-matching character in node->data
is greater (in ASCII) than that of param.*/
if (res > 0) return 1;
return 0;//if strings are equal
}
strhash_table * strhash_table_init(const unsigned int len)
{
super_list *list = (super_list *) malloc(sizeof(super_list) * len);
strhash_table * table = (strhash_table *) malloc(sizeof(strhash_table));
if(!table) return NULL;
table->len = len;
if (!list) return NULL;
for (unsigned int i = 0; i < len; i++) {
list[i].node = list_create();
list[i].len = 0;
}
table->list = list;
return table;
}
strhash_table * strhash_table_destroy(strhash_table * table)
{
unsigned int i;
super_list *list;
s_node *node, *next;
for (i = 0; i < table->len; i++) {
list = table->list + i;
node = list->node;
while (node) {
next = node->next;
free(node->data);
free(node);
node = next;
}
}
free(table->list);
free(table);
return table;
}
strhash_table * strhash_table_free(strhash_table * table)
{
unsigned int i;
super_list *list;
for (i = 0; i < table->len; i++) {
list = table->list + i;
if (list->len > 0) {
free(list->node->data);
list_destroy(list->node);
list->len = 0;
return table;
}
}
return table;
}
char * strhash_table_add(strhash_table * table, char * str)
{
char * to_insert = strdup(str);
int index = hashCode(str, table->len);
s_node *ordered_Add = list_ordered_append(&(table->list[index].node), compare_str_add, to_insert);
if (ordered_Add->data == to_insert)
table->list[index].len++;
else
free(to_insert);
return (char *) ordered_Add->data;
}
int find_str_node(s_node *node, void *param)
{
return strcmp((char *) node->data, (char *) param) == 0 ? 1 : 0;
}
strhash_table * strhash_table_remove(strhash_table * table, char * str)
{
const int index = hashCode(str, table->len);
if (table->list[index].len == 0) return table;
s_node *find_node;
const int result = list_process(table->list[index].node, &find_str_node, str, &find_node);
if (result == 1) {
free(find_node->data);
table->list[index].node = list_remove(table->list[index].node, find_node->data);
table->list[index].len--;
}
return table;
}
void strhash_table_info(strhash_table * table)
{
unsigned int i;
unsigned int len, min, max;
float deviation, moy;
len = max = min = table->list[0].len;
for (i = 1; i < table->len; i++) {
if (table->list[i].len > max) max = table->list[i].len;
else if (table->list[i].len < min) min = table->list[i].len;
len += table->list[i].len;
}
moy = (float)len / table->len;
deviation = 0;
for (i = 0; i < table->len; i++) {
deviation += (table->list[i].len - moy) * (table->list[i].len - moy);
}
deviation = (float) sqrt(deviation / table->len);
printf("Table hachage : ");
printf("%p\n",table);
printf("\tNombre total d'élément : " );
printf("%u\n",len );
printf("\tNombre minimum : ");
printf("%u\n", min);
printf("\tNombre maximum : ");
printf("%u\n", max );
printf("\tÉcart type du nombre d'éléments par entrée : ");
printf("%.2f\n", deviation );
return;
}
void strhash_print(strhash_table * table)
{
unsigned int i, j;
super_list *list;
s_node *node;
printf("\nHash table de %p\n", table);
printf("Start\n");
for (i = 0; i < table->len; i++) {
list = table->list + i;
printf("\t%d ---\n", i);
/****/
for (j = 0, node = list->node; j < list->len; j++, node = node->next)
{
printf( "\t\t%d. %s\n", j, (char *) node->data);
}
}
printf("End\n");
return;
}
/**** test file */
strhash_table * test_init(const unsigned int len)
{
strhash_table * table = strhash_table_init(len);
if (!table) {
printf("Tha HashTable hasn't been created\n");
assert(0);
}
printf("***Tha HashTable has been created***\n");
return table;
}
strhash_table * test_destroy(strhash_table * table){
table = strhash_table_destroy(table);
if (table->list->node) {
printf("The HashTable hasn't been destroyed (%p)\n", table->list->node);
assert(0);
}
printf("The HashTable has been destroyed\n");
return NULL;
}
int main(void)
{
strhash_table * table =strhash_table_init(10);
strhash_print(table);
strhash_table_add(table, "ele1");
strhash_table_add(table, "ele2");
strhash_table_add(table, "ele3");
strhash_table_add(table, "ele4");
strhash_table_add(table, "ele5");
//strhash_table_remove(table,"ele1");
//strhash_table_free(table);
test_destroy(table);
return 0;
}
Thank you in advance ^^
You should move list_destroy(list->node); outside the inner loop. You are freeing the node list multiple times inside a loop where you iterate on the node links.
Here is a modified version:
strhash_table *strhash_table_destroy(strhash_table *table) {
unsigned int i;
super_list *list;
s_node *node;
for (i = 0; i < table->len; i++) {
list = table->list + i;
for (node = list->node; node != NULL; node = node->next) {
free(node->data);
}
list_destroy(list->node);
}
free(table->list);
free(table);
return table;
}
void list_destroy(s_node *head) {
while (head) {
head = list_headRemove(head);
}
}
s_node *list_headRemove(s_node *head) {
if (!head) return head;
s_node *n = head->next;
free(head);
return n;
}
UPDATE
In the code posted, there are conflicting versions of functions list_destroy and list_headRemove, furthermore there are 2 calls to free(node); in the second function list_destroy, both of which are useless since node is a null pointer when the while loop exits.
UPDATE 2
There is a problem in strhash_table_free: you free list->node but you do not update list->node, so the list is freed a second time in strhash_table_destroy where list->len is not tested.
The field len in super_list seems redundant. You should just test if the node member is NULL and set it to NULL when the list is freed.
UPDATE 3
The final post is hardly minimal and does not show the problem... but I found some issues:
strhash_table_destroy returns table after freeing it: this is bad because table is now an invalid pointer. strhash_table_destroy should not return anything.
test_destroy dereferences table after strhash_table_destroy has freed it. This has undefined behavior. Remove this test function, just call strhash_table_destroy from main().
you free node->data in strhash_table_remove before passing it to list_remove, which is bad because node->data has become invalid.
worse: list_remove() does not test is the head node should be removed. In a minimal test case with a single element in the hash table, "ele1" is the head node, hence this node remains in the list, the len is decremented and becomes out of sync and the node has an invalid data pointer which will strhash_table_destroy will attempt to free, causing the double free issue.
strhash_table_free seems incorrect and inconsistent with strhash_table_destroy.
There are probably other issues in the code.
Here is a modified version with some simplifications and fixes:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
/**List header */
#ifndef LISTE_H
#define LISTE_H
struct _list_node {
void *data;
struct _list_node *next;
};
typedef struct _list_node s_node;
s_node *list_create(void);
void *list_get_data(s_node *node);
void list_set_data(s_node *node, void *data);
s_node *list_insert(s_node *head, void *data);
s_node *list_append(s_node *head, void *data);
s_node *list_process(s_node *head, int (*fct)(s_node *node, void *param), void *param);
s_node *list_ordered_append(s_node **head, int (*fct)(s_node *node, void *param), void *param);
s_node *list_headRemove(s_node *head);
s_node *list_remove(s_node *head, void *data);
void list_destroy(s_node *head);
void afficher_s_node(s_node *list);
int list_is_empty( s_node *node );
unsigned int list_size(s_node *node);
#endif
/**** c file list */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
//#include "list.h"
s_node *list_create(void) {
return NULL;
}
void *list_get_data(s_node *node) {
return node->data;
}
void list_set_data(s_node *node, void *data) {
node->data = data;
}
s_node *list_insert(s_node *head, void *data) {
s_node *node = (s_node *)malloc(sizeof(s_node));
if (node) {
list_set_data(node, data);
node->next = head;
return node;
} else {
return head;
}
}
s_node *list_append(s_node *head, void *data) {
if (!head) return list_insert(head, data);
s_node *node = head;
while (node->next) {
node = node->next;
}
node->next = list_insert(NULL, data);
return head;
}
s_node *list_process(s_node *head, int (*fct)(s_node *node, void *param), void *param) {
for (s_node *node = head; node; node = node->next) {
if (fct(node, param) == 1) {
return node;
}
}
return NULL;
}
s_node *list_ordered_append(s_node **head, int (*fct)(s_node *node, void *param), void *param) {
s_node *node;
int res;
// empty list
if (!*head) {
return *head = list_insert(*head, param);
}
// insert at head
res = fct(*head, param);
if (res > 0) {
return *head = list_insert(*head, param);
}
if (res == 0) {
return *head;
}
// generic case
for (node = *head; node->next; node = node->next) {
res = fct(node->next, param);
if (res > 1) {
return node->next = list_insert(node->next, param);
}
if (res == 0) {
return node->next;
}
}
// append node
return node->next = list_insert(NULL, param);
}
s_node *list_headRemove(s_node *head) {
if (head) {
s_node *n = head->next;
free(head);
return n;
} else {
return NULL;
}
}
s_node *list_remove(s_node *head, void *data) {
if (!head) return head;
if (head->data == data) {
head = list_headRemove(head);
} else {
for (s_node *node = head; node->next; node = node->next) {
if (node->next->data == data) {
node->next = list_headRemove(node->next);
break;
}
}
}
return head;
}
void list_destroy(s_node *head) {
while (head)
head = list_headRemove(head);
}
int list_is_empty(s_node *node) {
return node == NULL;
}
unsigned int list_size(s_node *node) {
unsigned int i = 0;
while (node) {
node = node->next;
i++;
}
return i;
}
/* hash table header */
#ifndef HACHAGE_H
#define HACHAGE_H
//#include "list.h"
typedef struct {
s_node *node;
unsigned int len;
} super_list;
typedef struct {
super_list *list;
unsigned int len;
} strhash_table;
strhash_table *strhash_table_init(const unsigned int len);
void strhash_table_destroy(strhash_table *table);
strhash_table *strhash_table_free(strhash_table *table);
char *strhash_table_add(strhash_table *table, const char *str);
int strhash_table_remove(strhash_table *table, const char *str);
void strhash_table_info(strhash_table *table);
void strhash_print(strhash_table *table);
#endif
/**** c file hash table */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
//#include "hachage.h"
//#include "list.h"
int hashCode(const char *str, unsigned int size_hash_table) {
unsigned int i, cle = 0;
for (i = 0; str[i] != '\0'; i++) {
cle *= 2;
cle += (int)str[i];
}
return cle % size_hash_table;
}
int compare_str_add(s_node *node, void *param) {
/* return <0 if node->data is before param, >0 if after, =0 if strings are equal */
return strcmp((const char *)node->data, (const char *)param);
}
strhash_table *strhash_table_init(const unsigned int len) {
strhash_table *table = (strhash_table *)malloc(sizeof(strhash_table));
super_list *list = (super_list *)malloc(sizeof(super_list) * len);
if (!table || !list) {
free(table);
free(list);
return NULL;
}
for (unsigned int i = 0; i < len; i++) {
list[i].node = list_create();
list[i].len = 0;
}
table->list = list;
table->len = len;
return table;
}
void strhash_table_destroy(strhash_table *table) {
for (unsigned int i = 0; i < table->len; i++) {
super_list *list = table->list + i;
s_node *node = list->node;
while (node) {
s_node *next = node->next;
free(node->data);
free(node);
node = next;
}
list->node = NULL;
}
free(table->list);
free(table);
}
char *strhash_table_add(strhash_table *table, const char *str) {
char *to_insert = strdup(str);
int index = hashCode(str, table->len);
s_node *ordered_Add = list_ordered_append(&table->list[index].node, compare_str_add, to_insert);
if (ordered_Add->data == to_insert) {
/* node was inserted: increase len */
table->list[index].len++;
} else {
/* node already present: free new data */
free(to_insert);
}
return (char *)ordered_Add->data;
}
int find_str_node(s_node *node, void *param) {
return strcmp((const char *)node->data, (const char *)param) == 0 ? 1 : 0;
}
// return 1 if successful
int strhash_table_remove(strhash_table *table, const char *str) {
int index = hashCode(str, table->len);
s_node *find_node = list_process(table->list[index].node, find_str_node, (void *)(uintptr_t)str);
if (find_node) {
/* node was found: free node and data */
void *data = find_node->data;
table->list[index].node = list_remove(table->list[index].node, data);
table->list[index].len--;
free(data);
return 1;
}
return 0;
}
void strhash_table_info(strhash_table *table) {
unsigned int i;
unsigned int len, min, max;
double deviation, moy;
len = max = min = table->list[0].len;
for (i = 1; i < table->len; i++) {
if (table->list[i].len > max) max = table->list[i].len;
else if (table->list[i].len < min) min = table->list[i].len;
len += table->list[i].len;
}
moy = (double)len / table->len;
deviation = 0;
for (i = 0; i < table->len; i++) {
deviation += (table->list[i].len - moy) * (table->list[i].len - moy);
}
deviation = sqrt(deviation / table->len);
printf("Table hachage : ");
printf("%p\n", (void *)table);
printf("\tNombre total d'élément : " );
printf("%u\n",len );
printf("\tNombre minimum : ");
printf("%u\n", min);
printf("\tNombre maximum : ");
printf("%u\n", max );
printf("\tÉcart type du nombre d'éléments par entrée : ");
printf("%.2f\n", deviation);
return;
}
void strhash_print(strhash_table *table) {
unsigned int i, j;
super_list *list;
s_node *node;
printf("\nHash table de %p\n", (void *)table);
printf("Start\n");
for (i = 0; i < table->len; i++) {
list = table->list + i;
printf("\t%d ---\n", i);
/****/
for (j = 0, node = list->node; j < list->len; j++, node = node->next) {
printf( "\t\t%d. %s\n", j, (char *)node->data);
}
}
printf("End\n");
}
/**** test file */
int main(void) {
strhash_table *table = strhash_table_init(10);
strhash_print(table);
strhash_table_add(table, "ele1");
strhash_table_remove(table, "ele1");
strhash_table_add(table, "ele1");
strhash_table_add(table, "ele2");
strhash_table_add(table, "ele3");
strhash_table_add(table, "ele4");
strhash_table_add(table, "ele5");
strhash_table_remove(table, "ele1");
strhash_print(table);
strhash_table_destroy(table);
return 0;
}
A cleaner way to do it in my opinion assuming you don't reuse list_headRemove and list_headRemove :
strhash_table *strhash_table_destroy(strhash_table *table) {
unsigned int i;
super_list *list;
s_node *node, *next;
for (i = 0; i < table->len; i++) {
list = table->list + i;
node = list->node;
while (node) {
next = node->next;
free(node->data);
free(node);
node = next;
}
}
free(table->list);
free(table);
return table; /* This pointer is not valid anymore be careful */
}
This following code must be able of add to ArrayList each process name since that current name still not is stored on list. The code of ArrayList implementation was from this reference, but have a trouble that, when changed int to UNICODE_STRING data (in Element structure, cause a sintaxe error on line:
if (e.data == list->elements[index].data) return index;
Error 1 error C2088: '==' : illegal for struct
of indexOf() routine.
So, how fix?
Code:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
#include <Winternl.h>
#pragma comment(lib,"ntdll.lib")
typedef struct _SYSTEM_PROCESS_INFO
{
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER Reserved[3];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
ULONG BasePriority;
HANDLE ProcessId;
HANDLE InheritedFromProcessId;
}SYSTEM_PROCESS_INFO, *PSYSTEM_PROCESS_INFO;
typedef struct
{
UNICODE_STRING data;
}Element;
typedef struct
{
int current;
int size;
int increment_rate;
Element *elements;
}ArrayList;
void initWithSizeAndIncRate(ArrayList *const list, int size, int rate)
{
list->size = size;
list->increment_rate = rate;
list->elements = (Element*)calloc(sizeof(Element), list->size);
list->current = -1;
}
void initWithSize(ArrayList *const list, int size)
{
initWithSizeAndIncRate(list, size, 50);
}
void init(ArrayList *const list)
{
initWithSize(list, 100);
}
void arraryCopy(void *dest, int dIndex, const void* src, int sIndex, int len, int destLen, size_t size)
{
uint8_t *udest = (uint8_t*)dest;
uint8_t *usrc = (uint8_t*)src;
dIndex *= size;
sIndex *= size;
len *= size;
destLen *= size;
if (src != dest)
{
memcpy(&udest[dIndex], &usrc[sIndex], len);
}
else
{
if (dIndex > sIndex)
{
uint8_t *tmp = (uint8_t*)calloc(destLen, size);
memcpy(tmp, &udest[dIndex], (destLen - dIndex));
memcpy(&udest[dIndex], &usrc[sIndex], len);
memcpy(&udest[dIndex + len], tmp, (destLen - dIndex));
free(tmp);
}
else if (sIndex > dIndex)
{
memcpy(&udest[dIndex], &usrc[sIndex], (destLen - sIndex) + 1);
}
else
return;
}
}
void clear(ArrayList *const list)
{
while (list->current >= 0)
{
list->elements[list->current] = (Element){ 0 };
list->current--;
}
}
void wide(ArrayList* const list)
{
list->size += list->increment_rate;
Element *newArr = (Element*)calloc(sizeof(Element), list->size);
arraryCopy(newArr, 0, list->elements, 0, list->current, list->size, sizeof(Element));
free(list->elements);
list->elements = newArr;
}
int add(ArrayList *const list, Element e)
{
if (++list->current < list->size)
{
list->elements[list->current] = e;
return 1;
}
else
{
wide(list);
list->elements[list->current] = e;
return 1;
}
return 0;
}
int indexOf(const ArrayList *const list, Element e)
{
int index = 0;
while (index <= list->current)
{
if (e.data == list->elements[index].data) return index;
index++;
}
return 0;
}
void printElement(const Element *const e)
{
printf("%i ", e->data);
}
void print(const ArrayList *const list)
{
int i;
for (i = 0; i <= list->current; i++)
{
Element e = list->elements[i];
printElement(&e);
}
printf("\n");
}
void clean(ArrayList *list)
{
free(list->elements);
}
int _tmain(int argc, _TCHAR* argv[])
{
NTSTATUS status;
PVOID buffer;
PSYSTEM_PROCESS_INFO spi;
ArrayList list;
init(&list);
buffer = VirtualAlloc(NULL, 1024 * 1024, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!buffer)
{
printf("\nError: Unable to allocate memory for process list (%d)\n", GetLastError());
return -1;
}
printf("\nProcess list allocated at address %#x\n", buffer);
spi = (PSYSTEM_PROCESS_INFO)buffer;
if (!NT_SUCCESS(status = NtQuerySystemInformation(SystemProcessInformation, spi, 1024 * 1024, NULL)))
{
printf("\nError: Unable to query process list (%#x)\n", status);
VirtualFree(buffer, 0, MEM_RELEASE);
return -1;
}
while (spi->NextEntryOffset)
{
printf("\nProcess name: %wZ | Process ID: %d\n", &spi->ImageName, spi->ProcessId);
int i = indexOf(&list, (Element){ spi->ImageName });
if (i > 0)
print("process already in list \n");
else
add(&list, (Element){ spi->ImageName });
spi = (PSYSTEM_PROCESS_INFO)((LPBYTE)spi + spi->NextEntryOffset);
}
VirtualFree(buffer, 0, MEM_RELEASE);
print(&list);
clean(&list);
_getch();
return 0;
}
EDIT:
After answer of #Johnny Mopp below, now how call correctly indexof routine?
I tried like this:
int i = indexOf(&list, (Element){ &spi->ImageName.Buffer });
if (i >= 0)
printf("process already in list \n");
else
add(&list, (Element){ &spi->ImageName.Buffer });
but indexof say that all already is present in list, this is wrong!
EDIT 2:
Error after first edition of answer:
IMAGE
UNICODE_STRING is a struct. You'll have to either do memcmp() on the entire struct or wcscmp() on e.data.Buffer
int indexOf(const ArrayList *const list, Element e)
{
int index = 0;
while (index <= list->current)
{
// Check same lengths and then do string compare
if (e.data.Length == list->elements[index].data.Length &&
0 == wcsncmp(e.data.Buffer,
list->elements[index].data.Buffer,
list->elements[index].data.Length))
return index;
index++;
}
return 0;
}
// Update after comment
Here's the whole thing with proper memory management of the UNICODE_STRINGs
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
#include <Winternl.h>
#pragma comment(lib,"ntdll.lib")
typedef struct _SYSTEM_PROCESS_INFO
{
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER Reserved[3];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
ULONG BasePriority;
HANDLE ProcessId;
HANDLE InheritedFromProcessId;
}SYSTEM_PROCESS_INFO, *PSYSTEM_PROCESS_INFO;
typedef struct
{
// Changed to be a pointer
UNICODE_STRING *data;
}Element;
typedef struct
{
int current;
int size;
int increment_rate;
Element *elements;
}ArrayList;
// Duplicate a UNICODE_STRING
UNICODE_STRING * CopyUString(UNICODE_STRING *src)
{
UNICODE_STRING *dest = (UNICODE_STRING *) malloc(sizeof UNICODE_STRING);
dest->Length = src->Length;
dest->MaximumLength = src->MaximumLength;
dest->Buffer = (PWSTR) malloc(sizeof WCHAR * dest->MaximumLength);
memcpy(dest->Buffer, src->Buffer, sizeof WCHAR * dest->MaximumLength);
return dest;
}
// Free a duplicated UNICODE_STRING
void FreeUString(UNICODE_STRING *src)
{
free(src->Buffer);
free(src);
}
void initWithSizeAndIncRate(ArrayList *const list, int size, int rate)
{
list->size = size;
list->increment_rate = rate;
list->elements = (Element*) calloc(sizeof(Element), list->size);
list->current = -1;
}
void initWithSize(ArrayList *const list, int size)
{
initWithSizeAndIncRate(list, size, 50);
}
void init(ArrayList *const list)
{
initWithSize(list, 100);
}
void arraryCopy(void *dest, int dIndex, const void* src, int sIndex, int len, int destLen, size_t size)
{
uint8_t *udest = (uint8_t*) dest;
uint8_t *usrc = (uint8_t*) src;
dIndex *= size;
sIndex *= size;
len *= size;
destLen *= size;
if (src != dest)
{
memcpy(&udest[dIndex], &usrc[sIndex], len);
}
else
{
if (dIndex > sIndex)
{
uint8_t *tmp = (uint8_t*) calloc(destLen, size);
memcpy(tmp, &udest[dIndex], (destLen - dIndex));
memcpy(&udest[dIndex], &usrc[sIndex], len);
memcpy(&udest[dIndex + len], tmp, (destLen - dIndex));
free(tmp);
}
else if (sIndex > dIndex)
{
memcpy(&udest[dIndex], &usrc[sIndex], (destLen - sIndex) + 1);
}
else
return;
}
}
void clear(ArrayList *const list)
{
while (list->current >= 0)
{
FreeUString(list->elements[list->current].data);
list->current--;
}
}
void wide(ArrayList* const list)
{
list->size += list->increment_rate;
Element *newArr = (Element*) calloc(sizeof(Element), list->size);
arraryCopy(newArr, 0, list->elements, 0, list->current, list->size, sizeof(Element));
free(list->elements);
list->elements = newArr;
}
int add(ArrayList *const list, Element *e)
{
if (++list->current < list->size)
{
list->elements[list->current].data = CopyUString(e->data);
return 1;
}
else
{
wide(list);
list->elements[list->current].data = CopyUString(e->data);
return 1;
}
return 0;
}
int indexOf(const ArrayList *const list, Element *e)
{
int index = 0;
while (index <= list->current)
{
// Check same lengths and then do string compare
if (e->data->Length == list->elements[index].data->Length &&
0 == wcsncmp(e->data->Buffer,
list->elements[index].data->Buffer,
list->elements[index].data->Length))
return index;
index++;
}
return 0;
}
void printElement(const Element *const e)
{
wprintf(L"%s ", e->data->Buffer);
}
void print(const ArrayList *const list)
{
int i;
for (i = 0; i <= list->current; i++)
{
Element e = list->elements[i];
printElement(&e);
}
printf("\n");
}
void clean(ArrayList *list)
{
free(list->elements);
}
int _tmain(int argc, _TCHAR* argv [])
{
NTSTATUS status;
PVOID buffer;
PSYSTEM_PROCESS_INFO spi;
ArrayList list;
init(&list);
buffer = VirtualAlloc(NULL, 1024 * 1024, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!buffer)
{
printf("\nError: Unable to allocate memory for process list (%d)\n", GetLastError());
return -1;
}
printf("\nProcess list allocated at address %#x\n", buffer);
spi = (PSYSTEM_PROCESS_INFO) buffer;
if (!NT_SUCCESS(status = NtQuerySystemInformation(SystemProcessInformation, spi, 1024 * 1024, NULL)))
{
printf("\nError: Unable to query process list (%#x)\n", status);
VirtualFree(buffer, 0, MEM_RELEASE);
return -1;
}
Element e;
while (spi->NextEntryOffset)
{
printf("\nProcess name: %wZ | Process ID: %d\n", &spi->ImageName, spi->ProcessId);
e.data = &(spi->ImageName);
int i = indexOf(&list, &e);
if (i > 0)
printf("process already in list \n");
else
add(&list, &e);
spi = (PSYSTEM_PROCESS_INFO) ((LPBYTE) spi + spi->NextEntryOffset);
}
VirtualFree(buffer, 0, MEM_RELEASE);
print(&list);
clean(&list);
_getch();
return 0;
}
I do not know why this is not working.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// struct of list
typedef struct noeud
{
int adresse, taille, temp;
struct noeud* suivant;
} * liste;
int random(int a, int b)
{
return (a + (rand() % ((b + 1) + a)));
}
void initialisation(liste* LBO)
{
*LBO = NULL;
}
I think it's here the problem when I create q (q is created to point to the previous node).
void creation(liste* LBO)
{
liste q, prec = NULL;
int i = 0;
srand(time(NULL));
while (i < 3)
{
printf("%d", i);
q = malloc(sizeof(liste));
if (*LBO == NULL)
{
q->adresse = 0;
q->taille = random(5, 45);
q->temp = random(5, 15);
q->suivant = *LBO;
*LBO = q;
i++;
}
else
{
prec = *LBO;
q->taille = random(5, 45);
q->temp = random(5, 15);
q->adresse = prec->adresse + prec->taille;
q->suivant = *LBO;
*LBO = q;
i++;
}
}
}
void affichage(liste LBO)
{
printf("\nvoici ta liste \n ");
while (LBO != NULL)
{
printf("%d-->", LBO->taille);
LBO = LBO->suivant;
}
if (LBO == NULL)
printf("NULL");
}
int main()
{
// or here
printf("Hello world!\n");
liste LBO;
initialisation(&LBO);
creation(&LBO);
affichage(LBO);
return 0;
}
There are several issues:
Instead of calling
initialisation(&LBO);
which is not really wrong, just write:
LBO = NULL;
Then don't hide pointers with typedefs, it only adds confusion.
Instead of:
typedef struct noeud
{
int adresse, taille, temp;
struct noeud* suivant;
} *liste;
Write:
struct noeud
{
int adresse, taille, temp;
struct noeud* suivant;
};
and use struct noeud* instead of liste.
Now the real problem:
This is wrong. Here you allocate the size for a pointer, but you need to allocate the size for the whole structure:
q = malloc(sizeof(liste));
which is actually the same as:
q = malloc(sizeof(struct noeud*))
but you need:
q = malloc(sizeof(struct noeud))
You see now why hiding pointers with typedefs is a bad idea.
So here is the corrected version of your program (#includes ommitted for brevity):
struct noeud
{
int adresse, taille, temp;
struct noeud* suivant;
};
int random(int a, int b)
{
return (a + (rand() % ((b + 1) + a)));
}
void creation(struct noeud** LBO)
{
struct noeud* q, *prec = NULL;
int i = 0;
// srand(time(NULL)); <<<<< don't call srand here, call it once at the
// beginning of the program
while (i < 3)
{
printf("%d", i);
q = malloc(sizeof(struct noeud));
if (*LBO == NULL)
{
q->adresse = 0;
q->taille = random(5, 45);
q->temp = random(5, 15);
q->suivant = *LBO;
*LBO = q;
i++;
}
else
{
prec = *LBO;
q->taille = random(5, 45);
q->temp = random(5, 15);
q->adresse = prec->adresse + prec->taille;
q->suivant = *LBO;
*LBO = q;
i++;
}
}
}
void affichage(struct noeud* LBO)
{
printf("\nvoici ta struct noeud* \n ");
while (LBO != NULL)
{
printf("%d-->", LBO->taille);
LBO = LBO->suivant;
}
// if (LBO == NULL) <<<<<<<<<<< drop this, LBO is always NULL here
// but it doesn't hurt, it's just useless
printf("NULL");
}
int main()
{
srand(time(NULL)); // <<<<<<<<<<<<< call srand here
struct noeud* LBO;
LBO = NULL;
creation(&LBO);
affichage(LBO);
return 0;
}
There is still room for improvement, especially the creation function is somewhat awkward.
Also look at the comments with <<<<<<<<<<<, there are minor corrections
So I wrote a toy program for fun, and at the I moment I finished debugging thinking I finally got everything right, the last check with valgrind gave me 2 errors for not freeing 2 blocks of memory. But the error message really does not make sense to me.
==7419== 80 bytes in 1 blocks are definitely lost in loss record 1 of 2
==7419== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7419== by 0x400C77: mj_Malloc (mj.c:19)
==7419== by 0x401761: main (choco.c:93)
==7419==
==7419== 80 bytes in 1 blocks are definitely lost in loss record 2 of 2
==7419== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7419== by 0x400C77: mj_Malloc (mj.c:19)
==7419== by 0x401776: main (choco.c:94)
==7419==
==7419== LEAK SUMMARY:
==7419== definitely lost: 160 bytes in 2 blocks
Line 94 and 93 in main is
mj_Thread *chocolateMakers = mj_Malloc(nMakers * sizeof *chocolateMakers);
mj_Thread *chocolateEaters = mj_Malloc(nEaters * sizeof *chocolateEaters);
which is freed by
mj_Free(chocolateEaters);
mj_Free(chocolateMakers);
mj_Malloc and mj_Free are simple wrappers for error checking. (mj_Free for consistency)
void *mj_Malloc(size_t size) {
void *p = malloc(size);
if (p == NULL) {
mj_Error("heap allocation failed");
}
return p;
}
void mj_Free(void *p) {
free(p);
}
You can see the whole code below if you want.
choco.c
#include "../mj.c"
typedef struct {
int n;
mj_BlockingQueue orderQueue;
mj_BlockingQueue deliveryQueue;
} *ChocolateArgument;
ChocolateArgument ChocolateArgumentCreate(int n, mj_BlockingQueue orderQueue, mj_BlockingQueue deliveryQueue) {
ChocolateArgument this = mj_Malloc(sizeof *this);
this->n = n;
this->orderQueue = orderQueue;
this->deliveryQueue = deliveryQueue;
return this;
}
int MakeChocolates(void *data) {
ChocolateArgument argument = (ChocolateArgument)data;
while (true) {
if (mj_BlockingQueueOut(argument->orderQueue) != NULL) {
printf("chocolate maker %i going home\n", argument->n);
break;
}
int milli = mj_RandomInt(1, 1000);
mj_Sleep(milli);
printf("new chocolate (maker %i, %.3f seconds)\n", argument->n, (double)milli / 1000.0);
int *pMakerNumber = mj_Malloc(sizeof *pMakerNumber);
*pMakerNumber = argument->n;
mj_BlockingQueueIn(argument->deliveryQueue, pMakerNumber);
}
mj_Free(data);
return EXIT_SUCCESS;
}
void HireChocolateMakers(mj_Thread **pMakers, int nMakers, mj_BlockingQueue orderQueue, mj_BlockingQueue deliveryQueue) {
*pMakers = mj_Malloc(nMakers * sizeof **pMakers);
for (int i = 0; i < nMakers; i += 1) {
ChocolateArgument argument = ChocolateArgumentCreate(i + 1, orderQueue, deliveryQueue);
(*pMakers)[i] = mj_ThreadCreate(MakeChocolates, argument);
}
printf("%i chocolate makers hired\n", nMakers);
}
int EatChocolates(void *data) {
ChocolateArgument argument = (ChocolateArgument)data;
int nOrders = mj_RandomInt(1, 10);
for (int i = 0; i < nOrders; i += 1) {
mj_BlockingQueueIn(argument->orderQueue, NULL);
}
printf("chocolate eater %i ordered %i chocolates\n", argument->n, nOrders);
for (int i = 1; i <= nOrders; i += 1) {
int *pMakerNumber = mj_BlockingQueueOut(argument->deliveryQueue);
printf("maker %i -> eater %i (%i / %i)\n", *pMakerNumber, argument->n, i, nOrders);
free(pMakerNumber);
}
printf("chocolate eater %i is satisfied\n", argument->n);
mj_Free(data);
return EXIT_SUCCESS;
}
void OrderChocolates(mj_Thread **pEaters, int nEaters, mj_BlockingQueue orderQueue, mj_BlockingQueue deliveryQueue) {
*pEaters = mj_Malloc(nEaters * sizeof **pEaters);
for (int i = 0; i < nEaters; i += 1) {
ChocolateArgument argument = ChocolateArgumentCreate(i + 1, orderQueue, deliveryQueue);
(*pEaters)[i] = mj_ThreadCreate(EatChocolates, argument);
}
}
void GoHome(mj_Thread *eaters, int nEaters, mj_Thread *makers, int nMakers, mj_BlockingQueue orderQueue) {
for (int i = 0; i < nEaters; i += 1) {
mj_ThreadWait(eaters[i]);
mj_ThreadDelete(eaters[i]);
}
printf("all chocolate eaters are satisfied\n");
for (int i = 0; i < nMakers; i += 1) {
mj_BlockingQueueIn(orderQueue, NULL + 1);
}
for (int i = 0; i < nMakers; i += 1) {
mj_ThreadWait(makers[i]);
mj_ThreadDelete(makers[i]);
}
}
int main(int argc, char **argv) {
if (argc != 3) {
mj_Error("not enough arguments");
}
int nMakers = atoi(argv[1]);
int nEaters = atoi(argv[2]);
mj_RandomSeed();
mj_BlockingQueue orderQueue = mj_BlockingQueueCreate();
mj_BlockingQueue deliveryQueue = mj_BlockingQueueCreate();
mj_Thread *chocolateMakers = mj_Malloc(nMakers * sizeof *chocolateMakers);
mj_Thread *chocolateEaters = mj_Malloc(nEaters * sizeof *chocolateEaters);
HireChocolateMakers(&chocolateMakers, nMakers, orderQueue, deliveryQueue);
OrderChocolates(&chocolateEaters, nEaters, orderQueue, deliveryQueue);
GoHome(chocolateEaters, nEaters, chocolateMakers, nMakers, orderQueue);
mj_BlockingQueueDelete(orderQueue);
mj_BlockingQueueDelete(deliveryQueue);
mj_Free(chocolateEaters);
mj_Free(chocolateMakers);
return 0;
}
mj.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <time.h>
#include <pthread.h>
#include <semaphore.h>
void mj_Error(char *errorMessage) {
fprintf(stderr, "%s\n", errorMessage);
exit(EXIT_FAILURE);
}
void *mj_Malloc(size_t size) {
void *p = malloc(size);
if (p == NULL) {
mj_Error("heap allocation failed");
}
return p;
}
void mj_Free(void *p) {
free(p);
}
typedef struct mj_QueueElement {
void *data;
struct mj_QueueElement *next;
} *mj_QueueElement;
mj_QueueElement mj_QueueElementCreate(void) {
mj_QueueElement this = mj_Malloc(sizeof *this);
return this;
}
void mj_QueueElementDelete(mj_QueueElement this) {
mj_Free(this);
}
typedef struct {
mj_QueueElement first;
mj_QueueElement last;
} *mj_Queue;
mj_Queue mj_QueueCreate(void) {
mj_Queue this = mj_Malloc(sizeof *this);
this->first = mj_QueueElementCreate();
this->last = this->first;
return this;
}
void mj_QueueDelete(mj_Queue this) {
mj_QueueElementDelete(this->first);
mj_Free(this);
}
void mj_QueueIn(mj_Queue this, void *data) {
this->last->data = data;
this->last->next = mj_QueueElementCreate();
this->last = this->last->next;
}
void *mj_QueueOut(mj_Queue this) {
mj_QueueElement temp = this->first;
void *data = temp->data;
this->first = this->first->next;
mj_QueueElementDelete(temp);
return data;
}
typedef pthread_mutex_t *mj_Mutex;
mj_Mutex mj_MutexCreate(void) {
mj_Mutex this = mj_Malloc(sizeof *this);
pthread_mutex_init(this, NULL);
return this;
}
void mj_MutexDelete(mj_Mutex this) {
pthread_mutex_destroy(this);
mj_Free(this);
}
void mj_MutexLock(mj_Mutex this) {
pthread_mutex_lock(this);
}
void mj_MutexUnlock(mj_Mutex this) {
pthread_mutex_unlock(this);
}
typedef sem_t *mj_Semaphore;
mj_Semaphore mj_SemaphoreCreate(int n) {
mj_Semaphore this = mj_Malloc(sizeof *this);
sem_init(this, 0, n);
return this;
}
void mj_SemaphoreDelete(mj_Semaphore this) {
sem_destroy(this);
mj_Free(this);
}
void mj_SemaphoreUp(mj_Semaphore this) {
sem_post(this);
}
void mj_SemaphoreDown(mj_Semaphore this) {
sem_wait(this);
}
typedef struct {
mj_Queue queue;
mj_Mutex inLock;
mj_Mutex outLock;
mj_Semaphore emptyBlocker;
} *mj_BlockingQueue;
mj_BlockingQueue mj_BlockingQueueCreate(void) {
mj_BlockingQueue this = mj_Malloc(sizeof *this);
this->queue = mj_QueueCreate();
this->inLock = mj_MutexCreate();
this->outLock = mj_MutexCreate();
this->emptyBlocker = mj_SemaphoreCreate(0);
return this;
}
void mj_BlockingQueueDelete(mj_BlockingQueue this) {
mj_QueueDelete(this->queue);
mj_MutexDelete(this->inLock);
mj_MutexDelete(this->outLock);
mj_SemaphoreDelete(this->emptyBlocker);
mj_Free(this);
}
void mj_BlockingQueueIn(mj_BlockingQueue this, void *data) {
mj_MutexLock(this->inLock);
mj_QueueIn(this->queue, data);
mj_SemaphoreUp(this->emptyBlocker);
mj_MutexUnlock(this->inLock);
}
void *mj_BlockingQueueOut(mj_BlockingQueue this) {
mj_MutexLock(this->outLock);
mj_SemaphoreDown(this->emptyBlocker);
void *data = mj_QueueOut(this->queue);
mj_MutexUnlock(this->outLock);
return data;
}
typedef pthread_t *mj_Thread;
typedef struct {
int (*function)(void *);
void *argument;
} *mj_ThreadInfo;
mj_ThreadInfo mj_ThreadInfoCreate(int (*function)(void *), void *argument) {
mj_ThreadInfo this = mj_Malloc(sizeof *this);
this->function = function;
this->argument = argument;
return this;
}
void *mj_ThreadFunction(void *data) {
mj_ThreadInfo info = (mj_ThreadInfo)data;
info->function(info->argument);
mj_Free(data);
return NULL;
}
mj_Thread mj_ThreadCreate(int (*function)(void *), void *argument) {
mj_Thread this = mj_Malloc(sizeof *this);
mj_ThreadInfo info = mj_ThreadInfoCreate(function, argument);
if (pthread_create(this, NULL, mj_ThreadFunction, info) != 0) {
mj_Error("failed to create thread");
}
return this;
}
void mj_ThreadDelete(mj_Thread this) {
mj_Free(this);
}
void mj_ThreadWait(mj_Thread this) {
pthread_join(*this, NULL);
}
void mj_Sleep(int milli) {
struct timespec time;
time.tv_sec = milli / 1000;
time.tv_nsec = (milli % 1000) * 1000000;
nanosleep(&time, NULL);
}
uint64_t mj_RandomInt_s;
uint64_t mj_RandomInt_s2;
void mj_RandomSeed(void) {
srand((unsigned)time(NULL));
mj_RandomInt_s = rand() * rand();
mj_RandomInt_s2 = rand() * rand() * rand();
}
int mj_RandomInt(int from, int to) {
if (from > to) {
mj_Error("invalid arguments");
}
uint64_t x = mj_RandomInt_s;
uint64_t y = mj_RandomInt_s2;
mj_RandomInt_s = y;
x ^= x << 23;
x ^= x >> 17;
x ^= y ^ (y >> 26);
mj_RandomInt_s2 = x;
return (int)((x + y) % (uint64_t)(to - from + 1)) + from;
}
You're allocating chocolateMakers twice (line 93 first and line 36 then) and chocolateEaters twice too (line 94 first and line 62 then). In both cases, you're overwriting the pointer resulting of the first allocation with the one resulting of the second allocation. When you free the allocated memory, you're doing it only once, with the pointers of the second allocations. The pointers of the first allocation are lost, the memory allocated is never freed.