#include <stdio.h>
#include <stdlib.h>
struct arrayADT {
int *A;
int size;
int length;
int *B;
int arr3;
};
struct arrayADT * MergeArray(struct arrayADT *arr1, struct arrayADT *arr2) { //we create thus in heap cuz we need to be able to use these in main function
struct arrayADT *arr3 = (struct arrayADT *)malloc((sizeof(struct arrayADT)));
int i, j, k;
i = j = k = 0;
while(i < arr1->length && j < arr1->length ) {
if(arr1->A[i] < arr2->A[j]) {
arr3->A[k] = arr1->A[i];
k++;
i++;
}
else {
arr3->A[k] = arr2->A[j];
k++;
j++;
}
}
for(; i<arr1->length ; i++) {
arr3->A[k] = arr1->A[i];
k++;
}
for(; j < arr2->length ; j++) {
arr3->A[k] = arr2->A[j];
k++;
}
arr3->length = arr1->length + arr2->length;
arr3->length = 10;
}
void main() {
struct arrayADT arr;
printf("Enter the size of an array");
scanf("%d", &arr.size);
arr.A = (struct arrayADT *)malloc(arr.size * sizeof(int));
arr.length = 0;
int n;
printf("enter the number of elements in an array");
scanf("%d", &n);
printf("enter the elements");
for(int i = 0; i < n; i++) {
scanf("%d", &arr.A[i]);
}
arr.length = n;
display(arr);
printf("Enter second array");
int j;
struct arrayADT *B = (struct arrayADT *)malloc((sizeof(struct arrayADT)));
for(j = 0; j < arr.length; j++) {
scanf("%d", &B[j]);
}
struct arrayADT *arr3 = (struct arrayADT *)malloc(sizeof(struct arrayADT));
arr3 = MergeArray(&arr, &B);
display(*arr3);
I was looking to merge these arrays using heap memory and I am getting segmentation fault. I am new to C programming with pointers and I have been struck here it would be so helpful if I passed this barrier with your help.
And I am not getting where my error lies it would be helpful if someone specifies that too, so that I can avoid these errors in future.
PS: I am using minGW compiler.
In general, your code is rater unorganized. There are several cases for undefined behaviour, for example you don't scan in the second array correctly. The most probably candidate for your segmentaion fault is here:
struct arrayADT *arr3 = (struct arrayADT *)malloc((sizeof(struct arrayADT)));
This will give you an uninitialized chunk of memory. The length and size could of arr3 be anything, and its data field A does not point to valid memory. Accessing it will likely crash.
You have three arrays in your code. You construct each step by step and you treat each differently. That leads to errors easily. Let's go about this more systematically.
Let's create a struct type for a fixed-size array: The maximum size must be given on creation and cannot change. The actual length of the array may be anything from 0 to its maximum size.
typedef struct Array Array;
struct Array {
int *value; // data array
int length; // actual length, 0 <= length <= size
int size; // maximum capacity
};
We create such arrays on the heap and because initializing the members is error-prone, we write a constructor:
Array *array_create(int size)
{
Array *array = calloc(1, sizeof(*array));
array->size = size;
array->value = calloc(size, sizeof(*array->value));
return array;
}
This function creates an empty array for at most size integers. If we allocate memory, we must de-allocate it later, so let's write a corresponding destructor function, which cleans up the ressources:
void array_destroy(Array *array)
{
if (array) {
free(array->value);
free(array);
}
}
After destroying an array, it can no longer be used, just as with memory after calling free() on it.
The array is at first empty, so let's write a function to add elements at its end if there is room:
void array_push(Array *array, int x)
{
if (array->length < array->size) {
array->value[array->length++] = x;
}
}
And a function to print it:
void array_print(const Array *array)
{
printf("[");
for (int i = 0; i < array->length; i++) {
if (i) printf(", ");
printf("%d", array->value[i]);
}
printf("]\n");
}
Now you can create arrays like so:
Array *a = array_create(10);
for (int i = 0; i < a->size; i++) {
array_push(a, i);
}
array_print(a);
array_destroy(a);
Your merge function will be simpler, too. Here's a full example. (But is uses generated array, not arrays typed in by the user.)
#include <stdio.h>
#include <stdlib.h>
typedef struct Array Array;
struct Array {
int *value;
int length;
int size;
};
Array *array_create(int size)
{
Array *array = calloc(1, sizeof(*array));
array->size = size;
array->value = calloc(size, sizeof(*array->value));
return array;
}
void array_destroy(Array *array)
{
if (array) {
free(array->value);
free(array);
}
}
void array_push(Array *array, int x)
{
if (array->length < array->size) {
array->value[array->length++] = x;
}
}
void array_print(const Array *array)
{
printf("[");
for (int i = 0; i < array->length; i++) {
if (i) printf(", ");
printf("%d", array->value[i]);
}
printf("]\n");
}
Array *merge(Array *a, Array *b)
{
Array *res = array_create(a->length + b->length);
int i = 0;
int j = 0;
while(i < a->length && j < b->length) {
if(a->value[i] < b->value[j]) {
array_push(res, a->value[i++]);
} else {
array_push(res, b->value[j++]);
}
}
while(i < a->length) {
array_push(res, a->value[i++]);
}
while(j < b->length) {
array_push(res, b->value[j++]);
}
return res;
}
int main(void)
{
Array *a = array_create(10);
Array *b = array_create(6);
Array *c;
for (int i = 0; i < a->size; i++) {
array_push(a, 1 + 3 * i);
}
for (int i = 0; i < b->size; i++) {
array_push(b, 4 + 2 * i);
}
array_print(a);
array_print(b);
c = merge(a, b);
array_print(c);
array_destroy(a);
array_destroy(b);
array_destroy(c);
return 0;
}
If you've read so far, here's the lowdown:
Organzie your code. That applies to code layout as much as writing small, generally applicable functions instead of doing everything "by hand". (The array type above is a bit on the fence: It uses functions, but getting at the data is still done via accessing the struct fields. You could even change the szie and length, whixh shouldn't really happen.)
Enable compiler warnings with -Wall. You will get useful information about potential (and often actual) errors.
Good luck!
Related
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 *.
I am new to threads and I have a program that uses threads to find the minimum number out of a 2d array and later on, it finds the distance that the other elements of the array have from the minimum number and stores them in another array.
The user should enter the size of the array and the number of threads he wants to use.
I tried the program below for 1d array and it worked just fine. When I converted it to work for a 2d array it started crashing and throwing a segmentation fault. I, however, cannot find which part of the 2d declaration is wrong.
Any help is really appreciated.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <pthread.h>
struct Parameters
{
// input
int s,p; //n is size of array, p is number of threads
int** array; //array with elements
int start;
int end;
// output
int smallest;
int pos; //position if minimum
int** B; //array that holds the distances
};
void* min(void* args)
{
struct Parameters* p = (struct Parameters*)args;
int **array = p->array;
int **B1 = p->B;
int start = p->start;
int end = p->end;
int smallest = array[start][start];
int pos = p->pos;
int distance;
//find the smallest
for (int i = start; i < end; i++)
{
for(int j = start; j < end; j++)
{
if (array[i][j] < smallest)
{
smallest = array[i][j];
pos = i;
}
}
}
//find the distances
for(int i = 0; i < ((struct Parameters*)args) -> s; i++)
{
for(int j = 0; j < ((struct Parameters*)args) -> s; j++)
{
distance = abs(pos - i);
B1[i][j] = distance;
}
}
params->smallest = smallest;
params->B = B1;
return NULL;
}
int main()
{
int smallest,pos;
int s,p;
struct Parameters *ptr = (struct Parameters *)malloc(sizeof(struct Parameters));
if(ptr == NULL)
{
printf("Not enough. Try again \n");
exit(0);
}
printf("Type s\n");
scanf("%d",&(ptr->s));
printf("Type p\n");
scanf("%d", &(ptr->p));
// declare an array of threads and associated parameter instances
pthread_t threads[(ptr->p)];
struct Parameters thread_parameters[(ptr->p)] ;
int arr[ptr->s][ptr->s];
int B2[ptr->s][ptr->s];
// intialize the array
for(int i=0; i< ptr->s; i++)
{
for(int j=0; j< ptr->s; j++)
{
printf("Type a \n");
scanf("%d",&arr[i][j]);
}
}
// smallest needs to be set to something
smallest = arr[0][0];
// start all the threads
for (int i = 0; i < ptr->p; i++)
{
memcpy(arr, thread_parameters[i].array, sizeof(arr));
thread_parameters[i].s = ptr->s;
memcpy(Bb, thread_parameters[i].B, sizeof(B2));
thread_parameters[i].start = i * (ptr->s / ptr->p);
thread_parameters[i].end = (i+1) * (ptr->s / ptr->p);
pthread_create(&threads[i], NULL, min, &thread_parameters[i]);
}
// wait for all the threads to complete
for (int i = 0; i < ptr->p; i++)
{
pthread_join(threads[i], NULL);
}
// Now aggregate the "smallest" and "largest" results from all thread runs
for (int i = 0; i < ptr->p; i++)
{
if (thread_parameters[i].smallest < smallest)
{
smallest = thread_parameters[i].smallest;
}
}
printf("Smallest is %d\n", smallest);
thread_parameters[ptr->p].B[ptr->s][ptr->s];
for (int i = 0; i < 1; i++)
{
for(int j = 0; j < ptr->s;j++)
{
for(int k = 0; k < ptr->s; k++)
{
printf("Element %d is %d away from min\n",j,thread_parameters[i].B[j][k]);
}
}
}
return 0;
}
Thank you!!
The issue with your code might also come from :
memcpy(arr, thread_parameters[i].array, sizeof(arr));
...
memcpy(Bb, thread_parameters[i].B, sizeof(B2));
as thread_parameters[i].array and thread_parameters[i].B are not allocated, if you are only reading the array it might b fine to only pass them by address
thread_parameters[i].array = arr
but for thread_parameters[i].B you would need to allocate the arrays and perform a deep copy (memcpy would not work)
The below text does not answer the question but does provide some insight on VLA usage
One reason for causing the segmentation with a declaration of a Variable Length Array is that the value is to large to allocate the array on the stack (some compiler choose this option, this choice might have performance reason).
The is not much option to recover cleanly from failure to allocate memory on the stack as there is little way to clean up stack memory during runtime within the same stack context.
You can mitigate the issue by allocating your 2D arrays on the heap instead, some of the strategies are available here(thanks #Lundin) and here.
int** alloc_2d_int_array(size_t rows, size_t cols) {
int **result = malloc(rows * sizeof(int *));
if(result == NULL) {
// could not allocate more memory
return NULL;
}
size_t row_size = cols * sizeof(int);
for(int i=0; i < rows; ++i) {
result[i] = malloc(row_size);
if(result[i] == NULL) {
// could not allocate more memory
// cleanup
return NULL;
}
}
return result;
}
the above implementation have not been tested, but does compile, there are still risk of integer overflow.
Then use the above define function as following:
int **arr = alloc_2d_int_array(ptr->s, ptr->s);
int **B2 = alloc_2d_int_array(ptr->s, ptr->s);
easier implementation (see here(thanks #Lundin))
int **arr = malloc(sizeof(int[ptr->s][ptr->s]);
int **B2 = malloc(sizeof(int[ptr->s][ptr->s]);
I'm trying to implement the mergesort algorithm using a dynamic array structure in c, but when i call the function to split the original array instead of getting two subarrays i get a seg fault error.
I'm pretty sure it has something to deal with how i define the size of my structure, but i cannot get over it. Here's how i've defined my structure and how i create and initialize it:
typedef struct dynarray
{
void **memory;
size_t allocated; //total size of the array
size_t used; //used size of the array
int index;
} dynarray;
//creates a new, empty, dynarray
void create_dynarray(dynarray **array, size_t size)
{
*array = calloc(size, sizeof(array));
(*array)->memory = NULL;
(*array)->allocated = 0;
(*array)->used = 0;
(*array)->index = -1;
}
This how i've defined my mergesort functions
//function used to slice the dynarray in two subarrays and call merge function
void* dynarray_mergesort(dynarray *param){
if(dynarray_length(param)>1){
param->index = 0;
printf("index of first:%d\t", param->index);
size_t size = param->used;
size_t m = size/2;
size_t n = size - size/2;
struct dynarray *l;
create_dynarray(&l, m);
printf("index of left:%d\t", l->index);
struct dynarray *r;
create_dynarray(&r, n);
printf("index of right:%d\n", r->index);
for(int i = 0 ; i < m; i++){
add_elem(l, param->memory[i]);
}for(int j = m; j < n; j++){
add_elem(r, param->memory[j]);
}
puts("first");
print_array(l);
puts("second");
print_array(r);
dynarray_mergesort(l);
dynarray_mergesort(r);
//dynarray_merge(param, l , r, size);
}
return param;
}
//function used to mergesort the array
void* dynarray_merge(dynarray *param, dynarray *l, dynarray *r, int size){
int i,j,k;
while(i < size/2 && j < size-size/2){
if(l->memory[i] < r->memory[j]){
param->memory[k] = l->memory[i];
i++;
k++;
}else{
param->memory[k] = r->memory[j];
j++;
k++;
}
}
while(i < size/2)
param->memory[k++] = l->memory[i++];
}while(j < size-size/2){
param->memory[k++] = r->memory[j++];
}
return param;
}
//function used to mergesort the array
void* dynarray_merge(dynarray *param, dynarray *l, dynarray *r, int size){
int i,j,k;
while(i < size/2 && j < size-size/2){
if(l->memory[i] < r->memory[j]){
param->memory[k] = l->memory[i];
i++;
k++;
}else{
param->memory[k] = r->memory[j];
j++;
k++;
}
}
while(i < size/2){
param->memory[k++] = l->memory[i++];
}while(j < size-size/2){
param->memory[k++] = r->memory[j++];
}
return param;
}
Probably i'm confused on how the size of my dynamic array is defined and how i have to treat it in my functions. Here's a compilable example to help you understand the problem. It is pretty long but most functions can be ignored as they are utility functions and they seem to work good. The problem is located in the mergesort function, but i'm afraid it could be related on how i've defined my dynarraystructure.
Ps. the line calling the dynarray_merge(param, l , r, size); is commented because i'm working on problems located in the dynarray_mergesort(dynarray *param);
Ps2: the printf functions called inside the dynarray_mergesort(dynarray *param); are used as debugging infos.
#include<stdio.h>
#include<stdlib.h>
typedef struct dynarray
{
void **memory;
size_t allocated;
size_t used;
int index;
} dynarray;
//get length of the dynarray
int dynarray_length(dynarray *array)
{
return array->index + 1;
}
//retrieves an element in a specific position of the dynarray
void* get_i_elem(dynarray *array,int index)
{
if (index < 0 || index > array->index) return NULL;
return array->memory[index];
}
//print arrays, useful to test
void print_array(dynarray *array)
{
for(int i = 0; i < dynarray_length(array); i++) {
printf("%d\t", *(int *)get_i_elem(array, i));
//puts("");
}
}
//creates a new, empty, dynarray
void create_dynarray(dynarray **array, size_t size)
{
*array = calloc(size, sizeof(array));
(*array)->memory = NULL;
(*array)->allocated = 0;
(*array)->used = 0;
(*array)->index = -1;
}
//adds a new element at the bottom of dynarray
void add_elem(dynarray *array, void *data)
{
size_t toallocate;
size_t size = sizeof(void *);
if ((array->allocated - array->used) < size){ // if M - N ...
toallocate = array->allocated == 0 ? size : (array->allocated * 2);
array->memory = realloc(array->memory, toallocate);
array->allocated = toallocate;
}
array->memory[++array->index] = data;
array->used = array->used + size;
}
//function used to slice the dynarray in two subarrays and call merge function
void* dynarray_mergesort(dynarray *param){
if(dynarray_length(param)>1){
param->index = 0;
printf("index of first:%d\t", param->index);
size_t size = param->used;
size_t m = size/2;
size_t n = size - size/2;
struct dynarray *l;
create_dynarray(&l, m);
printf("index of left:%d\t", l->index);
struct dynarray *r;
create_dynarray(&r, n);
printf("index of right:%d\n", r->index);
for(int i = 0 ; i < m; i++){
add_elem(l, param->memory[i]);
}for(int j = m; j < n; j++){
add_elem(r, param->memory[j]);
}
puts("first");
print_array(l);
puts("second");
print_array(r);
dynarray_mergesort(l);
dynarray_mergesort(r);
//dynarray_merge(param, l , r, size);
}
return param;
}
//function used to mergesort the array
void* dynarray_merge(dynarray *param, dynarray *l, dynarray *r, int size){
int i,j,k;
while(i < size/2 && j < size-size/2){
if(l->memory[i] < r->memory[j]){
param->memory[k] = l->memory[i];
i++;
k++;
}else{
param->memory[k] = r->memory[j];
j++;
k++;
}
}
while(i < size/2){
param->memory[k++] = l->memory[i++];
}while(j < size-size/2){
param->memory[k++] = r->memory[j++];
}
return param;
}
int main(){
struct dynarray *a;
create_dynarray(&a, 5);
int arr[5] = {18,14, 20,16,12};
int *ap = malloc(sizeof(int));
int *bp = malloc(sizeof(int));
int *cp = malloc(sizeof(int));
int *dp = malloc(sizeof(int));
int *ep = malloc(sizeof(int));
*ap = arr[0];
*bp = arr[1];
*cp = arr[2];
*dp = arr[3];
*ep = arr[4];
add_elem(a, ap);
add_elem(a, bp);
add_elem(a, cp);
add_elem(a, dp);
add_elem(a, ep);
dynarray_mergesort(a);
print_array(a);
}
In addition to the allocation shortfall mentioned in the comments below your question (e.g. needing *array = calloc(size, sizeof **array);), you have a simple error leading to your SegFault (you have other errors as well). You are storing the number of bytes in the size variable in dynarray_mergesort, not the number of pointers. So in dynarray_mergesort when you declare size_t size = param->used; your value of size is multiple of sizeof(void*) (e.g. sizeof(a_pointer)) times the number of pointers you have actually used. This leads to incorrect values for m and n.
To remedy the problem, you can simply do:
size_t size = param->used / sizeof(void*);
You have another error with your loop limits in:
for(size_t j = m; j < n; j++){
add_elem(r, param->memory[j]);
}
Where m = size/2; and n = size - size/2;. You actually need your limits of m -> size, e.g.:
for(size_t j = m; j < size; j++){
add_elem(r, param->memory[j]);
}
(note: above the proper type for i and j are both size_t to correspond to m and n and prevent "comparison between signed and unsigned integer expressions")
As noted in my comment, you have uninitialized value problems in dynarray_merge. You need to initialize i and k, e.g.
int i=0, j=0, k=0;
before you attempt:
i++;
k++;
With those changes your code runs to the end without problems (other than leaking memory):
$ ./bin/dynarraymergeorig
index of first:0 index of left:-1 index of right:-1
first
18 14
second
20 16 12
index of first:0 index of left:-1 index of right:-1
first
18
second
14
index of first:0 index of left:-1 index of right:-1
first
20
second
16 12
index of first:0 index of left:-1 index of right:-1
first
16
second
12
18
You still have problems merging your list (that is left to you to further investigate), but your SegFault issue is solved. Let me know if you have further questions. (other than on the changes required to fix your merge algorithm left to you)
The inside of the create_dynarray function
*array = calloc(size, sizeof(array));
should be changed to:
*array = calloc(size, sizeof(**array))
to do what you actually want to do (allocate a memory for the array with an element size dynarray * size).
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;
}
I'm new to C and have been trying to tackle this question. It's a continuation of the last thread I made. I made some progress but still have so much to learn and fix.
In short:
In this question a "vector" is a one dimensional array of integers. Therefore an array of vectors would be a two dimensional array that holds one dimensional arrays inside him.
I need to use these variables:
int** vectors- the 2D array
int size -an integer that represents how many vectors exist inside **vectors
int* sizes-a 1D array of integers that represents the length of the vectors
I need to write the following functions:
int init(int ***vectors, int **sizes, int size)
the function allocated memory to **vectors and *sizes with size and initializes vectors to be full of NULLs,and sizes to be full of zeros.
int set(int **vectors, int *sizes, int index, int *tmp, int tmp_size)
the function receives an array of nulls (**vectors)), frees the vector inside **vectors whose index is index and allocates memory for a new vector, whose length is tmp_size and places inside it *tmp's elements.
This is my code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int init(int*** vectors, int** sizes, int size)
{
int i, k,j;
*sizes = (int*)malloc(size * sizeof(int));
if (*sizes == NULL)
return 0;
for (j = 0; j < size; j++)
{
(*sizes)[j] = 0;
}
*vectors = (int**)malloc(size * sizeof(int*));
if (*vectors == NULL)
return 0;
for (i = 0; i < size; i++)
{
(vectors)[i] = NULL;
}
return 1;
}
int set(int **vectors, int *sizes, int index, int *tmp, int tmp_size)
{
if ((vectors)[index] != NULL)
{
free((vectors)[index]);
}
(vectors)[index] = (int*)malloc(tmp_size * sizeof(int));
if ((vectors)[index] == NULL)
return 0;
for (int b = 0; b < tmp_size; b++)
{
(vectors)[index][b] = tmp[b];
}
sizes[index] = tmp_size;
return 1;
}
int main()
{
int size, i, length, indexhere;
int** vectors = NULL;
int* sizes = NULL;
int* tmp = NULL;
int* p = &vectors;
int tempindex;
printf("\nPlease enter an amount of vectors:\n");
scanf("%d", &size);
init(p, &sizes, size);
printf("Enter index\n");
scanf("%d", &indexhere);
printf("Enter Length\n");
scanf("%d", &length);
tmp = (int*)malloc(length * sizeof(int));
printf("Enter elements:\n");
for (int g = 0; g < length; g++)
scanf("%d", &tmp[g]);
set(&vectors, sizes, indexhere, tmp, length);
system("pause");
return 0;
}
Could someone explain please why the program always crashes?
In init function (vectors)[i] = NULL; should actually be (*vectors)[i] = NULL;
When calling set function from main you should pass vectors instead of &vectors.
There also seems to be several pointer type mismatches in your code, so you should really pay attention to compiler's warnings. This is because C unfortunately allows implicit conversions between incompatible pointers, unlike C++ for example.
You call set like this
set(&vectors, sizes, indexhere, tmp, length);
but the first argument is declared as an int **. By passing &vector you're passing a pointer to vector, i.e. something of type int ***. This mismatch will lead to undefined behavior and probable crashes.
Here is a complete working example.
#include <stdio.h>
#include <stdlib.h>
void destroyVectors(int **vectors, int size)
{
for (int i = 0; i < size; i++)
{
free(vectors[i]);
}
}
int init(int*** vectors, int** sizes, int size)
{
int i, j;
*sizes = (int*)malloc(size * sizeof(int));
if (*sizes == NULL)
return 0;
for (j = 0; j < size; j++)
{
(*sizes)[j] = 0;
}
*vectors = (int**)malloc(size * sizeof(int*));
if (*vectors == NULL)
return 0;
for (i = 0; i < size; i++)
{
(*vectors)[i] = NULL;
}
return 1;
}
int set(int **vectors, int *sizes, int index, int *tmp, int tmp_size)
{
if ((vectors)[index] != NULL)
{
free((vectors)[index]);
}
(vectors)[index] = (int*)malloc(tmp_size * sizeof(int));
if ((vectors)[index] == NULL)
return 0;
for (int b = 0; b < tmp_size; b++)
{
(vectors)[index][b] = tmp[b];
}
sizes[index] = tmp_size;
return 1;
}
int main()
{
int size = 0, length = 0, indexhere = 0;
int** vectors = NULL;
int* sizes = NULL;
int* tmp = NULL;
printf("\nPlease enter an amount of vectors:\n");
scanf("%d", &size);
init(&vectors, &sizes, size);
printf("Enter index\n");
scanf("%d", &indexhere);
printf("Enter Length\n");
scanf("%d", &length);
tmp = (int*)malloc(length * sizeof(int));
printf("Enter elements:\n");
for (int g = 0; g < length; g++)
scanf("%d", &tmp[g]);
set(vectors, sizes, indexhere, tmp, length);
for(int i = 0; i < length; ++i)
printf("byte: %d\n", vectors[indexhere][i]);
printf("sizes index: %d\n", sizes[indexhere]);
free(tmp);
free(sizes);
destroyVectors(vectors, size);
return 0;
}