Reading a Structure using pointer second time gives segmentation fault error - c

When I read the second vector using vector_read() function or by intializing it to zero by usign vector_init_zero() I get segementation fault. I have searched it alot still not got the answer why it's happening. If I use only one pointer and don't initiallize it to 0 it works fine. Every other function works fine with single variable of structure pointer.
#include <stdio.h>
#include <stdlib.h>
typedef struct vector_s
{
int dim;
float *data_ptr;
} vector_type;
/* Allocate and initialize to 0 a vector with the given dimension */
void vector_init_zeros(vector_type *v_ptr, int dim)
{
v_ptr->dim = dim;
v_ptr->data_ptr = (float *)calloc(dim, sizeof(float));
#ifdef DEBUG
if (v_ptr->data_ptr == 0)
{
printf("vector_init_zeros error: calloc returned a null ptr\n");
exit(1);
}
#endif
}
/* Free up a vector that was allocated using vector_init_zeros */
void vector_deinit(vector_type *v_ptr)
{
v_ptr->dim = 0;
free(v_ptr->data_ptr);
v_ptr->data_ptr = 0;
}
/* Attempt to read a vector from stdin. */
/* Returns 1 if read successful and 0 otherwise */
int vector_read(vector_type *v_ptr)
{
int i;
float next;
for (i = 0; i < v_ptr->dim; i++)
{
if (scanf("%g\n", &next) != 1)
{
return 0;
}
v_ptr->data_ptr[i] = next;
}
return 1;
}
/* w = u + v */
void vector_add(vector_type *u_ptr, vector_type *v_ptr,
vector_type *w_ptr)
{
int i;
for (i = 0; i < v_ptr->dim; i++)
{
w_ptr->data_ptr[i] = u_ptr->data_ptr[i] + v_ptr->data_ptr[i];
}
}
/* v = cv */
void vector_scalar_mult(vector_type *v_ptr, float c)
{
int i;
for (i = 0; i < v_ptr->dim; i++)
{
v_ptr->data_ptr[i] = v_ptr->data_ptr[i] * c;
}
}
/* print the compondents of the given vector */
void vector_print(vector_type *v_ptr)
{
int i;
for (i = 0; i < v_ptr->dim; i++)
{
printf("%f ", v_ptr->data_ptr[i]);
}
printf("\n");
}
int main()
{
int dim;
int count = 0;
if (scanf("%d", &dim) != 1)
{
printf("Error reading the vector dimension from stdin\n");
exit(1);
}
vector_type *s,*t;
vector_init_zeros(s, dim);
vector_init_zeros(t, dim);
vector_read(s);
vector_read(t);
}

In main() where you declare s and t, you never initialize them. You can either declare them as structure variables and pass their addresses to the functions with the & 'address of' operator or allocate and deallocate them with malloc() and free() or equivalents.
int main(){
...
vector_type s, t;
...
vector_init_zeros(&s, dim);
vector_init_zeros(&t, dim);
vector_read(&s);
vector_read(&t);
}
or
int main(){
...
vector_type *s, *t;
s = (vector_type *) malloc(sizeof(vector_type));
t = (vector_type *) malloc(sizeof(vector_type));
...
free(s);
free(t);
}

Related

C, Segmentation fault while using dynamic array in struct

I'm trying to add new element to dynamic array in C (I know that I must free all memory. I will do it later), but I get this error every time:
But, what is strange, if I compile from terminal, like that, code works properly.
So, where is the error and how i can beat it?
Thank you!
All my code:
main.c
#include <stdio.h>
#include <stdlib.h>
typedef struct vector
{
int size;
int *array;
int alreadyIn;
}vector;
vector *vectorInit(int size)
{
vector *newVec = (vector *)malloc(sizeof(vector));
if(!newVec){printf("No memory!\n"); return NULL;}
newVec->size = size;
newVec->array = (int *)malloc(size * sizeof(int));
return newVec;
}
void allocNewMemory(vector *vect, int howMuch)
{
vect->array = (int *)realloc(vect->array ,(vect->size + howMuch) * sizeof(int));
vect->size += howMuch;
}
void pushBack(vector *vect, int number)
{
int howMuch = 5;
if(vect && vect->alreadyIn < vect->size)
{
vect->array[vect->alreadyIn] = number;
vect->alreadyIn++;
}
else
{
printf("Alloc new memory for %d elements...\n", howMuch);
allocNewMemory(vect, howMuch);
pushBack(vect, number);
}
}
void printVector(vector *vect)
{
for (int i = 0; i < vect->alreadyIn; i++)
{
printf("%d ", vect->array[i]);
}
printf("\n");
}
int main()
{
int startSize = 4;
vector * vec = vectorInit(startSize);
for (int i = 0; i < 6; i++)
{
pushBack(vec, i+1);
}
printVector(vec);
return 0;
}
You never initialize the alreadyIn member in the structure. That means its value will be indeterminate (and seemingly garbage or random).
You need to explicitly initialize it to zero:
vector *vectorInit(int size)
{
vector *newVec = malloc(sizeof(vector));
if(!newVec)
{
printf("No memory!\n");
return NULL;
}
newVec->size = size;
newVec->array = malloc(size * sizeof(int));
newVec->alreadyIn = 0; // Remember to set this to zero
return newVec;
}
This problem should have been easy to detect in the debugger.
Also note that I removed the casts from malloc. One should not cast the result of malloc, or really any function returning void *.

what is the issue with copyArray func in this c program ? the copyArray function is not working properly

** I would like to copy the pointer array to a new pointer so the original array won't change**
/* The main contains a pointer (p) to an array */
int main()
{
...
...
...
p = (int*)malloc(length*sizeof(int));
z = (int*)copyArray(p, length);
printArray(z, length);
return 0;
}
/* end of main */
CopyArray func
/* copy the array, return a new pointer to a new array with same size and values */
int copyArray(int *p, int length)
{
int *z = (int*)malloc(length*sizeof(int));
for(length--; length>=0; length--)
{
z[length] = p[length];
}
return *z;
}
printArray func
/* The function receives a pointer to an array and it's length. it will print the values that the array contains by the order */
void printArray(int *p, int length)
{
int i = 0;
for(; i<length; i++)
{
printf("\n %d \n", p[i]);
}
}
Reason for not working : return *z; here you are returning only one element *(z+0) = z[0] not the whole array. Check the code below:
#include <stdio.h>
#include <stdlib.h>
int *copyArray(int *p, int length) // Change return type to `int *`
{
int *z = malloc(length * sizeof(int)); // No need to cast output of malloc
for (length--; length >= 0; length--)
{
z[length] = p[length];
}
return z; // return the pointer.
}
void printArray(int *p, int length)
{
int i = 0;
for (; i < length; i++)
{
printf("\n %d \n", p[i]);
}
}
int main()
{
int *p;
int *z;
int length =5;
p = malloc(length*sizeof(int)); // No need of casting
for(int i=0 ;i<length; i++)
{
p[i] = i; // assigning some values
}
z = copyArray(p, length); // Donot cast return of the function
printArray(z, length);
return 0;
}
The output is :
0
1
2
3
4

Is it possible to dynamically allocate 2-D array in c with using calloc() once?

All the solutions I have seen online has calloc() function used twice, is it possible to do with only using it once?
The below code is not printing the correct array elements
int **ptr;
//To allocate the memory
ptr=(int **)calloc(n,sizeof(int)*m);
printf("\nEnter the elments: ");
//To access the memory
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",ptr[i][j]);
}
}
Since C99 you can use pointers to VLAs (Variable Length Arrays):
int n, m;
scanf("%d %d", &n, &m);
int (*ptr)[m] = malloc(sizeof(int [n][m]));
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
scanf("%d", &ptr[i][j]); // Notice the address of operator (&) for scanf
}
}
free(ptr); // Call free only once
If it's just about minimising the number of calls to memory allocation functions you can created such a jagged array like this:
#include <stdlib.h>
#include <stdio.h>
int ** alloc_jagged_2d_array_of_int(size_t n, size_t m)
{
int ** result = NULL;
size_t t = 0;
t += n * sizeof *result;
t += n*m * sizeof **result;
result = calloc(1, t);
if (NULL != result)
{
for (size_t i = 0; i < n; ++i)
{
result[i] = ((int*) (result + n)) + i*m;
}
}
return result;
}
Use it like this:
#include <stdlib.h>
#include <stdio.h>
int ** alloc_jagged_2d_array_of_int(size_t, size_t);
int main(void)
{
int result = EXIT_SUCCESS;
int ** p = alloc_jagged_2d_array_of_int(2, 3);
if (NULL == p)
{
perror("alloc_jagged_2d_array_of_int() failed");
result = EXIT_FAILURE;
}
else
{
for (size_t i = 0; i < 2; ++i)
{
for (size_t j = 0; j < 3; ++j)
{
p[i][j] = (int) (i*j);
}
}
}
/* Clean up. */
free(p);
return result;
}

Passing argument makes a pointer without cast?

I'm having an issue with compling the code.
I keep getting these errors.
"C: 194 warning passing argument 3 of 'matrix_column_subtract' makes pointer from integer without a cast"
"C: 12 note: expected 'double**' but argument is type 'int'
"C: 194 error too few arguments to function 'matrix_column_subtract'
I think I know what is going on I'm calling matrix_column_multiply is a void and I need to be calling it a pointer pointer I think and I don't know how to chage that. If anyone has some idea on how I can get this to compile that would be highly appreciated!!
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define DEBUG 0
#define MAX_ITER 10000
double *eigen (int n, double **A);
void qr_decomp (int n, double **A, double **Q, double **R);
void matrix_copy_column(double **msrc, int col1, double **mdst,int col2, int rows);
void matrix_column_subtract(double **m1, int c1, double **m2, int c2, int rows);
void matrix_column_multiply(double **m, int c, double k, int rows);
int main() {
int i, n = 126;
double *eig, **Am;
FILE *BinInp, *TxtOut;
/* Input Code: Reads bv, Am in binary form from CGrad.bin */
if ( (BinInp = fopen("CGrad.bin","r")) == NULL ) {
fprintf(stderr, "Cannot open matrix binary file INPUT... exiting\n");
exit(-1);
}
Am = (double**)malloc (n*sizeof(double*));
Am[0] = (double*)malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
Am[i] = Am[0] + i*n;
}
for (i = 0; i < n; i++) {
if (i==0) { /* Read one extra line that is discarded (bv is still in bin file) */
if (!fread(Am[i], sizeof(double), n, BinInp)) {
fprintf(stderr, "Cannot read row Am[%03d] of matrix... exiting\n", i+1);
exit(1);
}
}
if (!fread(Am[i], sizeof(double), n, BinInp)) {
fprintf(stderr, "Cannot read row Am[%03d] of matrix... exiting\n", i+1);
exit(1);
}
}
if (fclose(BinInp) == EOF) {
fprintf(stderr, "Cannot close matrix binary file INPUT... exiting\n");
exit(-1);
}
/* COMPUTE EIGENVALUES HERE USING FUNCTIONS. RETURN EIGENVALUES (AS 1D VECTOR) TO eig. */
if (DEBUG) printf ("Calling eigen\n");
eig = eigen (n, Am);
/* Output Code: Writes eig in text form to Eigs.txt */
if ( (TxtOut = fopen("Eigs.txt", "w")) == NULL ) {
fprintf(stderr, "Cannot open matrix text file OUTPUT... exiting\n");
exit(-1);
}
for (i = 0; i < n; i++) {
fprintf (TxtOut, "%18.14e ", eig[i]);
}
if (fclose(TxtOut) == EOF) {
fprintf(stderr, "Cannot close matrix text file INPUT... exiting\n");
exit(-1);
}
return 0;
}
double* eigen (int n, double **Acur)
{
double err = 1, eps = 1e-2;
double ndenom, nnumer, temp;
double *eig, **Anex, **Qsub, **Rsub;
int i, j, k, iters = 1;
/* Malloc memory for the three matricies */
Anex = malloc (n*sizeof(double*));
Anex[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
Anex[i] = Anex[0] + i*n;
}
Qsub = malloc (n*sizeof(double*));
Qsub[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
Qsub[i] = Qsub[0] + i*n;
}
Rsub = malloc (n*sizeof(double*));
Rsub[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
Rsub[i] = Rsub[0] + i*n;
}
/* Malloc memory for the return eig vector */
eig = malloc (n*sizeof(double));
for (i = 0; i < n; i++) {
eig[i] = 0;
}
/* Enter main iteration loop for eigenvalues */
while (err > eps && iters < MAX_ITER) {
/* QR Decompose Acur then find next iterate value in Anex */
qr_decomp (n, Acur, Qsub, Rsub);
// FIND NEXT ITERATE VALUE, PUT IN Anex.
/* Determine relative error change, reset "old" iterate value. */
ndenom = 0;
nnumer = 0;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
temp = Anex[i][j]-Acur[i][j];
ndenom += temp*temp;
nnumer += Anex[i][j]*Anex[i][j];
Acur[i][j] = Anex[i][j];
}
}
err = sqrt(ndenom)/sqrt(nnumer);
/* Increment the iteration count and report error */
if (iters % 25 == 0) {
printf ("Error at end of iteration %05d = %14.10f %%\n", iters, 100*err);
}
++iters;
}
printf ("Error at end of iteration %05d = %14.10f\nCONVERGED.\n", iters-1, err);
if (iters == MAX_ITER) {
printf ("WARNING: MAX_ITER iterations reached!...\n");
}
/* Copy diagonal entries of Acur into eig for return to main */
for (i=0; i<n; i++) {
eig[i] = Acur[i][i];
}
return eig;
}
void qr_decomp (int n, double **Adec, double **myQ, double **myR)
{
int i, j, k; /* Loop Variables: this is all you should need! */
double **T, **S;
double r;
T = malloc (n*sizeof(double*));
T[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
T[i] = T[0] + i*n;
}
S = malloc (n*sizeof(double*));
S[0] = malloc (n*n*sizeof(double));
for (i = 1; i < n; ++i) {
S[i] = S[0] + i*n;
}
/* Main loop for decomposition */
for (i=0; i<n; i++) {
/* Column i of Q is initially column i of A */
matrix_copy_column(Adec,i,myQ,i,n);
/* For j < i-1, Perform the dot product between the j row of Q and the
i row of A to determine the R(j,i) value, then insure the Q i column
is orthogonal to all other Q columns by subtracting existing Q columns
from it. */
for (j = 0; j < i; j++) {
//r[j,i] = Qj^T * Ui
matrix_copy_column(myQ,j,T,0,n);
matrix_copy_column(Adec,i,S,0,n);
for (k=0; k<n; k++) {
r += T[k][0] * S[k][0];
}
/* Determine the R diagonal as the magnitude of the Q column, then
normalize the Q column (make it a unit vector). */
//Qi = Ui
myR[j][i] = r;
// Something wrong here.
// There is one parameter missing, as matrix_column_subtract needs 5 parameters and
// only 4 are given.
// Also, matrix_column_multiply is defined as returning a void, whereas the 3rd parameter
// of matrix_column_subtract should be a double **
matrix_column_subtract(myQ,i,matrix_column_multiply(T,0,r,n),j);
}
}
}
/* Copies a matrix column from msrc at column col1 to mdst at column col2 */
void matrix_copy_column(double **msrc, int col1, double **mdst,int col2, int rows) {
int i = 0;
for (i=0; i<rows; i++) {
mdst[i][col2] = msrc[i][col1];
}
}
/* Subtracts m2's column c2 from m1's column c1 */
void matrix_column_subtract(double **m1, int c1, double **m2, int c2, int rows) {
int i = 0;
for (i=0; i<rows; i++) {
m1[i][c1] -= m2[i][c2];
}
/*return m1;*/
}
void matrix_column_multiply(double **m, int c, double k, int rows) {
int i = 0;
for (i=0; i<rows; i++) {
m[i][c] *= k;
}
/*return m;*/
}
A problem is here.
matrix_column_subtract(myQ,i,matrix_column_multiply(T,0,r,n),j);
The relevant function signatures are:
void matrix_column_subtract(double **m1, int c1, double **m2, int c2, int rows);
void matrix_column_multiply(double **m, int c, double k, int rows);
Note that matrix_column_multiply returns void, but you're passing it in as if it were double **. I'm guessing the compiler is desperately trying to make it work and returned some sort of garbage integer.
These functions return void because they do their work directly on the matrix in question. matrix_column_multiply alters m. matrix_column_subtract alters m1.
To make it work, call matrix_column_multiply on T then pass T (now modified by the multiplication) into matrix_column_subtract.
matrix_column_multiply(T, 0, r, n);
matrix_column_subtract(myQ, i, T, j, ...rows...);
You're still missing the fifth argument, rows. I'm going to guess that's n, same as has been used for the rows in every other matrix_column_blah call.

Read and write to dynamically allocated array

I have a text file containing a matrix N by 3 of float numbers. I need to read the matrix and put the data into a dynamically allocated array. I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define X_ 0
#define Y_ 0
#define Z_ 0
#define VERTEX_COUNT 3
void read_data(FILE* FILE_POINTER, float **GRID, int N_LINES)
{
int i = 0, j=0;
for(i = 0; i < N_LINES; i++)
{
for(j = 0; j < VERTEX_COUNT; j++)
{
if (!fscanf(FILE_POINTER, "%f", &GRID[i][j]))
break;
}
}
}
int find_length(FILE* FILE_POINTER)
{
int ch = 0;
int length = 0;
if(FILE_POINTER != NULL)
{
while(!feof(FILE_POINTER))
{
ch = fgetc(FILE_POINTER);
if(ch == '\n')
{
length++;
}
}
}
else
{
perror("File not found");
exit(EXIT_FAILURE);
}
return length;
}
int main()
{
/* Define variables needed*/
int i=0,j=0;
float** GRID_GEOM;
float** GRID_TOPO;
/* Open the files containing the data*/
FILE* FILE_GEOM = fopen("temporary_geom.txt","r");
FILE* FILE_TOPO = fopen("temporary_topo.txt","r");
/* Find length of the data set*/
int N_POINTS = find_length(FILE_GEOM);
int N_TRIANG = find_length(FILE_TOPO);
/* Dynamically allocate memory for each data set*/
GRID_GEOM = malloc(N_POINTS * sizeof(float*));
for (i = 0; i < N_POINTS; i++)
{
GRID_GEOM[i] = malloc(VERTEX_COUNT * sizeof(float));
}
GRID_TOPO = malloc(N_TRIANG * sizeof(float*));
for (i = 0; i < N_TRIANG; i++)
{
GRID_TOPO[i] = malloc(VERTEX_COUNT * sizeof(float));
}
/* Read data into the arrays*/
read_data(FILE_GEOM, GRID_GEOM, N_POINTS);
/* Close the files */
fclose(FILE_GEOM);
fclose(FILE_TOPO);
/* Free the memory allocated */
for (i = 0; i < N_POINTS; i++)
{
free(GRID_GEOM[i]);
}
free(GRID_GEOM);
for (i = 0; i < N_TRIANG; i++)
{
free(GRID_TOPO[i]);
}
free(GRID_TOPO);
}
When I try to access any position in the matrix GRID_GEOM, all values seem to be 0. I can't figure out why.
In function find_length, you read the whole file so when you pass the file pointer to read_data, it already points to the end of it.
You can either rewind the pointer, or close the file and reopen it again for parsing data.

Resources