How does memory reallocated for an array inside a struct - c

In the code below, when memory is reallocated with
g->alist[u] = realloc(g->alist[u], sizeof(struct successors) +
sizeof(int) * (g->alist[u]->len - 1))
how can numbers be added to list[] using
g->alist[u]->list[g->alist[u]->d++] = v
if it was initialized as list[1]?
struct graph {
int n;
int e;
struct successors {
int d;
int len;
char is_sorted;
int list[1];
} *alist[1];
};
typedef struct graph *Graph;
Graph graph_create(int n)
{
Graph g;
int i;
g = malloc(sizeof(struct graph) + sizeof(struct successors*) * (n - 1));
assert(g);
g->v = n;
g->e = 0;
for (i = 0; i < n; i++)
{
g->alist[i] = malloc(sizeof(struct successors));
assert(g->alist[i]);
g->alist[i]->d = 0;
g->alist[i]->len = 1;
g->alist[i]->is_sorted = 1;
}
return g;
}
void graph_add_edge(Graph g, int u, int v)
{
assert(u >= 0);
assert(u < g->v);
assert(v >= 0);
assert(v < g->v);
while(g->alist[u]->d >= g->alist[u]->len)
{
g->alist[u]->len *= 2;
g->alist[u] = realloc(g->alist[u], sizeof(struct successors) +
sizeof(int) * (g->alist[u]->len - 1));
}
g->alist[u]->list[g->alist[u]->d++] = v;
g->alist[u]->is_sorted = 0;
g->e++;
}

Related

Critical error detected c0000374. MergeSort.exe has triggered a breakpoint

I was trying to implement merge sort in C.
But when I test the code I encounter this error c0000374 in my merge sort function when I try to split array into left right array.
The code is as follows.
typedef struct EntryStruct {
int data;
char *name;
} Entry;
typedef char *String;
void merge(Entry *output, Entry *L, int nL, Entry *R, int nR) {
int i = 0;
int j = 0;
int k = 0;
while (k < nL + nR) {
if ((L[i].data != NULL && L[i].data < R[i].data) || R[j].data == NULL) {
output[k] = L[i];
i++;
} else {
output[k] = R[j];
j++;
}
k++;
}
}
void merge_sort(Entry *entries, int n) {
if (n > 1) {
int mid = n / 2;
Entry *temp = (Entry *)malloc(n * sizeof(Entry));
Entry *left = (Entry *)malloc(mid * sizeof(Entry));
Entry *right = (Entry *)malloc((n - mid) * sizeof(Entry));
for (int l = 0; l < mid; l++)
left[l] = entries[l];
for (int r = mid; r < n; r++)
right[r] = entries[r];
merge_sort(left, mid);
merge_sort(right, n - mid);
merge(temp, left, mid, right, n - mid);
for (int i = 0 ; i < n; i++) {
entries[i] = temp[i];
}
free(temp);
}
}
Entry Entry_create(int data, String name) {
Entry node;
node.name = (String)malloc(strlen(name) + 1);
strcpy(node.name, name);
node.data = data;
return node;
}
void printArrByName(Entry *arr, int s) {
for (int i = 0; i < s; i++) {
printf("%s\n", arr[i].name);
}
}
int main(void) {
Entry *arr = malloc(5 * sizeof(*arr));
arr[0] = Entry_create(5, "abc");
arr[1] = Entry_create(6, "def");
arr[2] = Entry_create(2, "ghijk");
arr[3] = Entry_create(3, "ksdljf");
arr[4] = Entry_create(1, "lsdfjl");
merge_sort(arr, 5);
printArrByName(arr, 5);
free(arr);
}
I want to ask what is the cause of this problem in my case and how to solve it.
Is this happen because I split array in to left right in the wrong way or is it something to do with the initialization of the array.
There are multiple problems in the code causing undefined behavior:
[major: undefined behavior] In the merge_sort function, the loop for (int r = mid; r < n; r++) right[r] = entries[r]; accesses the array pointed to by right beyond the end. You should write:
for (int r = mid; r < n; r++)
right[r - mid] = entries[r];
This bug is a good candidate to explain the observed behavior as it corrupts the malloc() internal data, causing a subsequent call to malloc() to crash.
[major: memory leak] You do not free left, nor right. As a matter of fact, allocating copies of the left and right parts of the array is not even necessary.
[major: undefined behavior] In the merge function, you do not test if i is less than nL, nor of j is less than nR before accessing L[i] or R[j]. Testing if the data member is not NULL does not suffice, accessing an element beyond the end of an array has undefined behavior.
[minor: unstable sort] L[i].data < R[i].data might not preserve the order of entries that have the same data value. You should use L[i].data <= R[i].data to implement stable sorting.
[hint] Defining typedef char *String; is a bad idea. Do not hide pointers behind typedefs, it is confusing and error prone.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct EntryStruct {
int data;
char *name;
} Entry;
#ifdef _MSC_VER
// define strdup on legacy systems
char *strdup(const char *s) {
size_t len = strlen(s);
char *p = (char *)malloc(len + 1);
if (p)
memcpy(p, s, len + 1);
return p;
}
#endif
void merge(Entry *output, Entry *L, int nL, Entry *R, int nR) {
int i = 0;
int j = 0;
int k = 0;
while (k < nL + nR) {
if (i < nL && (j >= nR || L[i].data <= R[j].data)) {
output[k] = L[i];
i++;
} else {
output[k] = R[j];
j++;
}
k++;
}
}
void merge_sort(Entry *entries, int n) {
if (n > 1) {
int mid = n / 2;
Entry *temp;
Entry *left = entries;
Entry *right = entries + mid;
merge_sort(left, mid);
merge_sort(right, n - mid);
temp = (Entry *)malloc(n * sizeof(Entry));
merge(temp, left, mid, right, n - mid);
for (int i = 0; i < n; i++) {
entries[i] = temp[i];
}
free(temp);
}
}
Entry Entry_create(int data, const char *name) {
Entry node;
node.name = strdup(name);
node.data = data;
return node;
}
void printArrByName(Entry *arr, int n) {
for (int i = 0; i < n; i++) {
printf("%s\n", arr[i].name);
}
}
int main(void) {
Entry *arr = malloc(5 * sizeof(*arr));
arr[0] = Entry_create(5, "abc");
arr[1] = Entry_create(6, "def");
arr[2] = Entry_create(2, "ghijk");
arr[3] = Entry_create(3, "ksdljf");
arr[4] = Entry_create(1, "lsdfjl");
merge_sort(arr, 5);
printArrByName(arr, 5);
for (int i = 0; i < 5; i++)
free(arr[i].name);
free(arr);
return 0;
}
Although not needed for small arrays, and since there are answers based on the questions code, here is a somewhat optimized top down merge sort that avoids copy backs by using a pair of mutually recursive functions (...a2a, ...a2b). An entry function does a one time allocation of the temporary array. On my system, it takes less than .5 second to sort an array of 4 million structures.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct EntryStruct {
int data;
char *name;
} Entry;
/* prototypes for mutually recursive functions */
void merge_sort_a2a(Entry *a, Entry *b, int ll, int ee);
void merge_sort_a2b(Entry *a, Entry *b, int ll, int ee);
void merge(Entry *a, Entry *b, int ll, int rr, int ee)
{
int o = ll; /* b[] index */
int l = ll; /* a[] left index */
int r = rr; /* a[] right index */
while(1){
if(a[l].data <= a[r].data){ /* if a[l] <= a[r] */
b[o++] = a[l++]; /* copy a[l] */
if(l < rr) /* if not end of left run */
continue; /* continue (back to while) */
while(r < ee) /* else copy rest of right run */
b[o++] = a[r++];
break; /* and return */
} else { /* else a[l] > a[r] */
b[o++] = a[r++]; /* copy a[r] */
if(r < ee) /* if not end of right run */
continue; /* continue (back to while) */
while(l < rr) /* else copy rest of left run */
b[o++] = a[l++];
break; /* and return */
}
}
}
void merge_sort_a2a(Entry *a, Entry *b, int ll, int ee)
{
int rr;
if(ee - ll < 2){ /* if 1 element */
return; /* return */
}
rr = ll + (ee-ll)/2; /* mid point, start of right run */
merge_sort_a2b(a, b, ll, rr);
merge_sort_a2b(a, b, rr, ee);
merge(b, a, ll, rr, ee);
}
void merge_sort_a2b(Entry *a, Entry *b, int ll, int ee)
{
int rr;
if(ee - ll < 2){ /* if 1 element */
b[ll] = a[ll]; /* copy to b */
return;
}
rr = ll + (ee-ll)/2; /* mid point, start of right run */
merge_sort_a2a(a, b, ll, rr);
merge_sort_a2a(a, b, rr, ee);
merge(a, b, ll, rr, ee);
}
void merge_sort(Entry *a, int n) {
if(n < 2)
return;
Entry *b = malloc(n * sizeof(Entry));
merge_sort_a2a(a, b, 0, n);
free(b);
}
Entry Entry_create(int data, const char *name) {
Entry node;
node.name = _strdup(name); /* _strdup is ISO name */
node.data = data;
return node;
}
void printArrByName(Entry *arr, int n) {
for (int i = 0; i < n; i++) {
printf("%s\n", arr[i].name);
}
}
int main(void) {
Entry *arr = malloc(5 * sizeof(*arr));
arr[0] = Entry_create(5, "abc");
arr[1] = Entry_create(6, "def");
arr[2] = Entry_create(2, "ghijk");
arr[3] = Entry_create(3, "ksdljf");
arr[4] = Entry_create(1, "lsdfjl");
merge_sort(arr, 5);
printArrByName(arr, 5);
for (int i = 0; i < 5; i++)
free(arr[i].name);
free(arr);
return 0;
}

Valgrind Block are Lost

I'm trying to understand why the follow code is wrong using valgrind. The problem apparently is in the function destroy_poli, I say this because when I comment this part of the main function
poli ** p = (poli **) malloc( sizeof( poli *) * npols );
for(k=0;k<npols;k++) {
p[k] = new_poli( nvars, w );
}
for(k=0;k<npols;k++)
destroy_poli(p[k]);
free(p);
I get 0 errors with valgrind. Please Could you help to undersantd where my error is?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bits.h"
#include "parsemap.h"
#include "galois.h"
#define ANF 1
#define pos(i,j) (((1+i)*i)/2 + j)
int *table_red;
typedef struct _mono {
int w;
char ** v;
} mono;
typedef struct _poli {
int nvars;
mono ** p;
} poli;
void destroy_mono(mono * m){
int i=0;
for(i=0;i<2*(m->w);i++)
free(m->v[i]);
free(m->v);
}
void destroy_poli(poli * p){
int nvars = p->nvars;
int i;
for(i=0;i<((nvars+1)*nvars)/2;i++)
destroy_mono(p->p[i]);
free(p->p);
}
mono * new_mono( int w, int idx ) {
int i;
mono * r = (mono *) malloc( sizeof(mono) );
r->w = w;
r->v = (char **) malloc( sizeof(char *)*( 2*w ) );
for( i = 0; i < 2*w; i++ ) {
r->v[i] = (char *) malloc( sizeof(char )*( 4096 ) );
r->v[i][0] = 0;
}
return r;
}
poli * new_poli( int nvars, int w ) {
poli * p = (poli *) malloc( sizeof(poli) );
p->nvars = nvars;
int i,j;
nvars++;
p->p = (mono **) malloc( sizeof( mono * ) * ((nvars+1)*nvars)/2);
nvars--;
for(i=0; i < nvars; i++ )
for(j=0; j <=i; j++ )
p->p[pos(i,j)] = new_mono( w, i );
}
return p;
}
void create_table( int w ) {
table_red = (int *) malloc( sizeof( int ) * 2 * w );
int i, j, a, b;
for(i=0;i<2*w;i++) {
table_red[i] = mod( (1 << i), w );
}
}
int ** read_input( int * npols, int * nvars, int * w, int ** enc ) {
int i, j;
*npols = 1;
*nvars = 1;
int nv = *nvars + 1;
int np = *npols;
*enc = (int *) malloc( sizeof( int) * np );
for(i=0; i < np; i++ ) {
(*enc)[i] = 0;
}
int ** coefs = (int **) malloc( sizeof( int *) * np );
for(i=0; i < np; i++ ) {
coefs[i] = (int *) malloc( sizeof( int) * ((nv+1)*nv)/2 );
for(j=0; j < ((nv+1)*nv)/2; j++)
coefs[i][j] = 0;
}
return coefs;
}
int main(int argc, char ** argv) {
int nvars;
int npols;
int i;
int w = 2, *enc;
int ** coefs = read_input( &npols, &nvars, &w, &enc );
int k, j;
create_table( w );
npols = 1;
poli ** p = (poli **) malloc( sizeof( poli *) * npols );
for(k=0;k<npols;k++) {
p[k] = new_poli( nvars, w );
}
for(k=0;k<npols;k++)
destroy_poli(p[k]);
free(p);
for(i=0; i < npols; i++ )
free(coefs[i]);
free(coefs);
free(enc);
return 0;
}
==24066== 16 bytes in 1 blocks are definitely lost in loss record 2 of 3
==24066== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24066== by 0x400CE8: new_poli (in /home/grados-sanchez/workspace/mq2sat/mq2sat/mq2sat)
==24066== by 0x400FD7: main (in /home/grados-sanchez/workspace/mq2sat/mq2sat/mq2sat)
==24066==
==24066== 16 bytes in 1 blocks are definitely lost in loss record 3 of 3
==24066== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24066== by 0x400C46: new_mono (in /home/grados-sanchez/workspace/mq2sat/mq2sat/mq2sat)
==24066== by 0x400D70: new_poli (in /home/grados-sanchez/workspace/mq2sat/mq2sat/mq2sat)
==24066== by 0x400FD7: main (in /home/grados-sanchez/workspace/mq2sat/mq2sat/mq2sat)
==24066==
You are missing free(p) in destroy_poli() and free(m) in destroy_mono(). I was able to determine that by compiling with -g and using valgrind to check the line nunmber where the leaked pointer was allocated tracking it led me to find the problem. Another thing I did was write the code in a way that it can be debugged and maintained, please check this and tell me whether or not it's worth the effort
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define ANF 1
#define pos(i, j) (((1 + (i)) * (i)) / 2 + (j))
int *table_red;
typedef struct _mono
{
int w;
char **v;
} mono;
typedef struct _poli
{
int nvars;
mono **p;
} poli;
void
destroy_mono(mono *m)
{
if (m == NULL)
return;
for (int i = 0 ; i < 2 * m->w ; i++)
free(m->v[i]);
free(m->v);
free(m);
}
void
destroy_poli(poli *p)
{
if (p == NULL)
return;
for (int i = 0 ; i < ((p->nvars + 1) * p->nvars) / 2 ; i++)
destroy_mono(p->p[i]);
free(p->p);
free(p);
}
mono *
new_mono(int w, int idx)
{
mono *r;
r = malloc(sizeof(*r));
if (r == NULL)
exit(-1);
r->w = w;
r->v = malloc(2 * w * sizeof(*r->v));
if (r->v == NULL)
exit(-1);
for (int i = 0 ; i < 2 * w ; i++)
{
r->v[i] = malloc(4096);
if (r->v[i] == NULL)
exit(-1);
r->v[i][0] = 0;
}
return r;
}
poli *
new_poli(int nvars, int w)
{
poli *p;
p = malloc(sizeof(*p));
if (p == NULL)
exit(-1);
p->nvars = nvars++;
p->p = malloc(((nvars + 1) * nvars * sizeof(*p->p)) / 2);
if (p->p == NULL)
exit(-1);
nvars -= 1;
for (int i = 0 ; i < nvars ; i++)
{
for (int j = 0 ; j <= i ; j++)
p->p[pos(i, j)] = new_mono(w, i);
}
return p;
}
void
create_table(int w)
{
table_red = malloc(2 * w * sizeof(*table_red));
if (table_red == NULL)
exit(-1);
for (int i = 0 ; i < 2 * w ; i++)
table_red[i] = mod((1 << i), w);
}
int **
read_input(int *npols, int *nvars, int *w, int **enc)
{
int i, j;
int **coefs;
int nv;
int np;
*npols = 1;
*nvars = 1;
nv = *nvars + 1;
np = *npols;
enc[0] = malloc(sizeof(**enc) * np);
if (enc[0] == NULL)
exit(-1);
for (i = 0 ; i < np ; i++)
enc[0][i] = 0;
coefs = malloc(sizeof(*coefs) * np);
if (coefs == NULL)
exit(-1);
for (i = 0 ; i < np ; i++)
{
coefs[i] = malloc(((nv + 1) * nv) / 2 * sizeof(**coefs));
if (coefs[i] == NULL)
exit(-1);
for (j = 0 ; j < ((nv + 1) * nv) / 2 ; j++)
coefs[i][j] = 0;
}
return coefs;
}
int main(int argc, char ** argv)
{
int nvars;
int npols;
int i;
int w;
int *enc;
int **coefs;
int k;
poli **p;
w = 2;
coefs = read_input(&npols, &nvars, &w, &enc);;
create_table(w);
npols = 1;
p = malloc(npols * sizeof(*p));
for (k = 0 ; k < npols ; k++) {
p[k] = new_poli(nvars, w);
}
for (k = 0 ; k < npols ; k++)
destroy_poli(p[k]);
free(p);
for (i = 0 ; i < npols ; i++)
free(coefs[i]);
free(coefs);
free(enc);
return 0;
}

Double free after setting pointer to NULL

Note: this may appear as a duplicate to a prior question I had asked. I have taken the comments on that question to produce a more concise and runnable version.
I have patched the memory leaks as pointed out in a prior post. Now, I am receiving a double free error. I have commented where I believe the double free error is occurring - within the power_arr() function. I have posted another question, operating the trim() function utilizing the same pattern, without receiving an error. I am trying to understand the exact cause of the double free error, as the management of the pointer tmp within power_arr() appears sound.
The exact error message is as follows:
*** Error in `./a.out': double free or corruption (fasttop): 0x00000000017a5fc0 ***
Aborted
The purpose of the code is to handle large integers as an array of integers. More specifically, to handle integers in the range of 2^1000.
Side note, the function pad() and the enum SIDE. Given the array int n[] = { 1, 2 };. Calling pad() with SIDE set to LOW, i.e. 0, and a new_length of 5, the array returned is as follows; { 0, 0, 0, 1, 2 }. If the SIDE were set to HIGH, the result would be { 1, 2, 0, 0, 0 }.
#include <stdlib.h>
#include <stdio.h>
#define MAX(a, b) (a > b) ? a : b
#define MIN(a, b) (a < b) ? a : b
enum SIDE { LOW, HIGH };
int *pad(int *n, int nlength, int new_length, enum SIDE side);
int *sum(int *n, int nlength, int *m, int mlength, int *sum_length);
int *power_arr(int *n, int nlength, int exp, int *res_length);
int *trim(int *n, int nlength, int *res_length);
void copy(int *to, int *from, int length);
int main(void)
{
int b[] = { 2 };
int r, i;
int *rlength, *res;
r = 0;
rlength = &r;
res = power_arr(b, 1, 4, rlength);
printf("Length = %d\n", *rlength);
for (i = 0; i < *rlength; i++)
{
printf("i = %d\n", res[i]);
}
free(res);
exit(0);
}
int *pad(int *n, int nlength, int new_length, enum SIDE side)
{
int i, j;
int *padded;
if (nlength < 1 || new_length <= nlength)
{
return NULL;
}
padded = calloc(new_length, sizeof(int));
if (!padded)
{
return NULL;
}
if (side == LOW)
{
j = new_length - 1;
for (i = (nlength - 1); i >= 0; i--)
{
padded[j--] = n[i];
}
}
else
{
j = 0;
for (i = 0; i < nlength; i++)
{
padded[j++] = n[i];
}
}
return padded;
}
int *trim(int *n, int nlength, int *res_length)
{
int i, j;
int *res;
for (i = 0; i < nlength; i++)
{
if (n[i] > 0)
{
break;
}
}
*res_length = (nlength - i);
res = malloc(sizeof(int) * (*res_length));
if (!res)
{
return NULL;
}
j = 0;
while (i < nlength)
{
res[j++] = n[i++];
}
return res;
}
int *sum(int *n, int nlength, int *m, int mlength, int *sum_length)
{
int i, tmp, carry, padded;
int *result, *trimmed, *op1, *op2;
enum SIDE side = LOW;
if (nlength == mlength)
{
op1 = n;
op2 = m;
}
else if (nlength > mlength)
{
op1 = n;
op2 = pad(m, mlength, nlength, side);
padded = 1;
}
else
{
op1 = m;
op2 = pad(n, nlength, mlength, side);
padded = 1;
}
result = malloc(sizeof(int) * (MAX(nlength, mlength) + 1));
if (!op1 || !op2 || !result)
{
if (padded)
{
free(op2);
}
free(result);
return NULL;
}
carry = 0;
for (i = (MAX(nlength, mlength)) - 1; i >= 0; i--)
{
tmp = op1[i] + op2[i] + carry;
if (carry > 0)
{
carry = 0;
}
if (tmp >= 10)
{
carry = tmp / 10;
tmp = tmp % 10;
}
result[i + 1] = tmp;
}
if (padded)
{
free(op2);
}
if (carry > 0)
{
result[0] = carry--;
}
*sum_length = (MAX(nlength, mlength)) + 1;
trimmed = trim(result, *sum_length, sum_length);
free(result);
return trimmed;
}
void copy(int *to, int *from, int length)
{
int i;
for (i = 0; i < length; i++)
{
to[i] = from[i];
}
}
int *power_arr(int *n, int nlength, int exp, int *res_length)
{
int *tmp, *rt, *bufp;
int bufp_length, i, dbg_i;
rt = malloc(sizeof(int) * 1000);
bufp = malloc(sizeof(int) * 1000);
if (!rt || !bufp)
{
free(rt);
free(bufp);
return NULL;
}
copy(rt, n, nlength);
copy(bufp, n, nlength);
*res_length = bufp_length = nlength;
while (--exp > 0)
{
for (i = *n - 1; i > 0; i--)
{
tmp = sum(rt, *res_length, bufp, bufp_length, res_length);
if (!tmp)
{
printf("tmp was null\n");
exit(-1);
}
copy(rt, tmp, *res_length);
if (tmp)
{
free(tmp); // double-free error occurs here, on subsequent iterations
tmp = NULL;
}
}
copy(bufp, rt, *res_length);
bufp_length = *res_length;
}
free(bufp);
return rt;
}
Note, I would have deleted the original question that this one evolved from, but I feel this is a branch off from my "Malloc returning same value - no double free error" question. As subsequent debugging in that question lead to this one.
padded was undefined in sum(). By initializing padded to zero, the free() logic executes correctly.

How do I traverse a memory block in a struct with pointers?

Goal:
Traverse the vertices memory block in the Heap struct.
Errors: I get expected unqualified-id before ‘(’ token when trying to access vertices. Also, ‘vertices’ was not declared in this scope.
Header:
typedef struct Heap *PriorityQueue_t;
typedef struct HeapItem *PriorityItem_t;
PriorityQueue_t Init(int max_capacity, int source_vertex);
Implementation:
#include "heap.h"
#include <stdlib.h>
#include <limits.h>
struct Heap
{
int size;
PriorityItem_t vertices;
};
struct HeapItem
{
int id;
int distance;
};
PriorityQueue_t Init(int max_capacity, int source_vertex)
{
PriorityQueue_t Q;
Q = (PriorityQueue_t)malloc(sizeof(PriorityQueue_t));
Q->vertices = (PriorityItem_t)malloc(sizeof(PriorityItem_t)*max_capacity);
Q->size = max_capacity;
int i;
for(i = 0; i < Q->size; i++)
{
Q->(vertices + i)->id = i; //Errors on this line.
Q->(vertices + i)->distance = INT_MAX;
}
Q->(vertices + source_vertex)->distance = 0;
return Q;
}
You've placed the parens in the wrong place. Try this:
(Q->vertices + i)->id = i; //Errors on this line.
(Q->vertices + i)->distance = INT_MAX;
}
(Q->vertices + source_vertex)->distance = 0;
Q->(vertices + i)->id = i; //Errors on this line.
Q->(vertices + i)->distance = INT_MAX;
Q->(vertices + source_vertex)->distance = 0;
You can't do that like that...
Q->vertices[i].id = i;
(Q->vertices + i)->distance = INT_MAX;
(*(Q->vertices + source_vertex)).distance = 0; // Not sensible, but legal
You can avoid a lot of parentheses by using plain indexing and removing the casts:
PriorityQueue_t Init(int max_capacity, int source_vertex)
{
PriorityQueue_t Q;
Q = malloc(sizeof *Q);
Q->vertices = malloc(max_capacity * sizeof *Q->vertices);
Q->size = max_capacity;
int i;
for(i = 0; i < Q->size; i++)
{
Q->vertices[i].id = i;
Q->vertices[i].distance = INT_MAX;
}
// maybe add next line:
// assert (source_vertex >=0 && source_vertex < Q->size);
Q->vertices[source_vertex].distance = 0;
return Q;
}

Using a structure in a recursive function (referenced structure)

I'm having problems understanding how to write code that solves the following problem: I have a structure containing a 2D-array. Then I have a recursive function that take a pointer to the structure as an argument and I want the recursive function to be able to manipulate the structure sent, not a local copy.
The struct is initialized in the function initStruct, where memory for the 2D-array is allocated. The recursive function builds up an array and at a specific point calls a function to insert it into the structure's array.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int** spBasis(int);
void mpBasis(int**, int, int, int, int, int, int, int*, struct mpBasis *, int, int);
void initMpBasis(struct mpBasis *, int, int);
void insertMpState(struct mpBasis *, int *);
struct mpBasis {
int** basis;
int size;
int capacity;
};
int main() {
int a, b, c, d;
char maxE[256];
char noParticles[256];
char P[256];
char M[256];
FILE *fp;
int **spStates;
struct mpBasis *mp;
int mpState[6] = {0, 0, 0, 0, 0, 0};
printf("Input max e for sp states, no of particles, parity (1 for odd and 0 for even) and magnetic projection: ");
gets(maxE);
gets(noParticles);
gets(P);
gets(M);
spStates = spBasis(atoi(maxE));
fp = fopen("spStates.txt", "a+");
fprintf(fp, "E\tj\tl\tm\n");
for (a = 0; a < 330; a++) {
fprintf(fp, "State %d: ", a+1);
for (b = 0; b < 4; b++) {
fprintf(fp, "%d\t", spStates[a][b]);
}
fprintf(fp, "\n");
}
mp = malloc(sizeof(struct mpBasis));
initMpBasis(mp, 5449, 6);
for (c = 0; c < 5449; c++) {
for (d = 0; d < 6; d++) {
fprintf(fp, "%d: %d\t", c, mp->basis[c][d]);
}
fprintf(fp, "\n");
}
printf("%p\n", (void*) mp);
printf("hello 3");
mpBasis(spStates, 0, atoi(maxE), 0, atoi(M), 0, atoi(P), mpState, mp, 0, 0);
fclose(fp);
return 0;
}
int** spBasis(int maxE) {
int c;
int i, j, k, l;
int q = 0;
int** spStates;
spStates = (int**)malloc(330 * sizeof(int *));
for (c = 0; c < 330; c++) {
spStates[c] = malloc(4 * sizeof(int));
}
for (i = 0; i <= maxE; i++) {
for (j = i % 2; j <= i; j += 2) {
for (k = -(2 * j + 1); k <= (2 * j + 1); k += 2) {
spStates[q][0] = i;
spStates[q][1] = j;
spStates[q][2] = 2 * j + 1;
spStates[q][3] = k;
q += 1;
}
for (l = -(2 * j - 1); l <= (2 * j - 1); l += 2) {
spStates[q][0] = i;
spStates[q][1] = j;
spStates[q][2] = 2 * j - 1;
spStates[q][3] = l;
q += 1;
}
}
}
return spStates;
}
void mpBasis(int** spStates, int e, int maxE, int m, int M, int l,
int P, int * mpState, struct mpBasis *mpB, int position, int lastSpState) {
int i;
for (i = lastSpState; i < 330; i++) {
if (e > maxE) {
break;
} else if (position == 5) {
if (m == M && l % 2 == P) {
insertMpState(mpB, mpState);
break;
}
} else {
// add spState to mpState and make the recursive call for the next position
mpState[position] = i;
mpBasis(spStates, e + spStates[i][0], maxE, m + spStates[i][3], M,
l + spStates[i][1], P, mpState, mpB, position+1, i);
}
}
}
void initMpBasis(struct mpBasis *a, int initialSize, int sizeY) {
int c;
a->basis = (int **)malloc(initialSize * sizeof(int*));
for (c = 0; c < initialSize; c++) {
a->basis[c] = (int *) malloc(sizeY * sizeof(int));
}
a->size = 0;
a->capacity = initialSize;
}
void insertMpState(struct mpBasis *a, int* mpState) {
/*if (a->size == a->capacity) {
a->size *= 2;
a->basis = (int **)realloc(a->basis, a->size * sizeof(int));
}*/
a->basis[a->size++] = mpState;
}
Added all the code.
The problem is that after the recursive function has been called, the "basis" array in structure mpBasis still only contains random values, i.e. the mpBasis function hasn't done anything with it. Am I passing the mp argument by value here?
Thanks for your help!
The first step is to compile with warnings enabled. Eg if you are using GCC you can use option -Wall -Wextra.
EDIT:
(previous listing of >20 errors removed)
Ok, since you are using Visual Studio, enable warnings like this:
Open the project's Property Pages dialog box.
Select C/C++.
On the General property page, modify the Warning Level to /W4

Resources