C array of pointers and malloc - c

I'm trying to get data from std stored into an array, using pointers. The main declares d as int *d; and the function is called using x = getdata(&d); When I step through it with gdb it dies at the first iteration of the for loop, when it tries *d[i]=val;
int getdata(int **d)
{
int count,val,i,j=0;
scanf("%d", &count);
d = malloc(sizeof *d * count);
for( i = 0; i < count-1; i++) {
scanf("%d",val);
*d[i]=val;
}
for ( i = 0; i < count; i++)
printf("Number %d\n",*d[i]);
return count;
}

The memory should be allocated as follows
*d = malloc(count * sizeof **d);
The values should be accessed as follows
(*d)[i] = val;
It is also not clear why you allocate count elements and only initialize count - 1 elements in the input cycle (and later print all count elements in output cycle).

*d = malloc(count * sizeof(int));
then
(*d)[i] = val

What you have is a pointer to an array, not an array of pointers.
1) malloc returns a void* so you need to assign the result to *d instead of d
2) the data size you want is of an int, not an int* (using *d gets you an int* where **d is an int)
*d = malloc(sizeof(**d) * count);
3) Indexing the array requires slightly different syntax
(*d)[i] = val;
printf("%d\n", (*d)[i]);
4) The second scanf needs a pointer, not an int
scanf("%d", &val);

Related

New beginner for dynamically allocated Array. Why do I have segmentation fault here?

I use nested data structure for fibonacci, but I have a segmentation fault 11.
void fib(int **fib_array, int n){
fib_array = malloc(n * sizeof(int*));
for(int i = 0; i < n; i++){
fib_array[i] = malloc(sizeof(int));
}
for(int i = 0; i < n; i++){
if (i <= 1){
fib_array[i][0] = i;
}
else{
fib_array[i][0] = fib_array[i - 2][0] + fib_array[i - 1][0];
}
}
}
int main(int argc, char **argv) {
/* do not change this main function */
int count = strtol(argv[1], NULL, 10);
int *fib_sequence;
fib(&fib_sequence, count);
for (int i = 0; i < count; i++) {
printf("%d ", fib_sequence[i]);
}
free(fib_sequence);
return 0;
}
you are being too complicated. You just need a single malloc
*fib_array = malloc(n * sizeof(int));
and remove you second indexings [0] from everywhere
The consfusion comes from **int. This looks like a multi dim array. Its not - its declared ** so that you can set the value in the caller. A simpler exampe will help
void Make42(int* v)
{
*v = 42;
}
int main()
{
int myv = 0;
Make42(&myv);
// now myv == 42
}
The * in the arg list is so that Make42 can 'reach out' and modify what was passed to it (myv in this case)
In your code the ** on fib array is there for the same purpose. you could have done (In know you werent allowed to by the test definition )
int *fib(int n){
int *fib_array = malloc(n * sizeof(int));
......
return fib_array;
}
and in main
fib_sequence = fib(count);
this makes it much clearer that you are really manipulating a simple array
pm100 is right, but a little short for answering to a beginner...
At first, you have passed a pointer to a pointer. If you want the original pointer to contain a value, you need to dereference the pointer to pointer:
*fib_array = ...
By assigning to the pointer only (as you did in your code), you do not modify the orignial pointer (fib_sequence in main) at all. And as you have not initialised it, it might point to anywhere, thus the segmentation fault when you try to print the values of it.
Then why an array of pointers to individually stored values? You can use a contiguous array of ints, which you get by
*fib_array = malloc(n * sizeof(int));
OK, further usage won't be too nice ((*fib_array)[i] = ...), so I recommend a temporary variable instead:
int* fa = malloc(n * sizeof(int));
// now fill in the values comfortably:
fa[i] = ...;
// finally, assign the pointer to the target:
*fib_array = fa;
Side note: always check the result of malloc, it could be NULL:
fa = ...
if(fa)
// assign values
else
// appropriate error handling
In your concrete case, you could omit the else branch in your function and check your pointer outside within main function.
By the way, a simple return value would have made your live easier, too:
int* fib(int n)
{
int* fib_array = malloc(n * sizeof(int*));
// ...
return fib_array;
}
Notice: no need for pointer to pointer... Usage:
int* fib_sequence = fib(count);

sprintf Producing segmentation fault

I am getting a segmentation fault from the below program.
#include <stdio.h>
#include <string.h>
void removeProcess(int*, int);
void removeProcessN(char**, int, int);
void main() {
int numPro = 0, quanTime = 0, contTime = 0, i, elemNum, time = 0;
//Supply variables with user input
printf("Enter number of processes: ");
scanf("%d", &numPro);
printf("Enter context switch time: ");
scanf("%d", &contTime);
printf("Enter quantum of time: ");
scanf("%d", &quanTime);
//Create array of number of process time
int proTime[numPro];
//Create string array for better output
char *proNames[numPro];
//Retrieves process time from user
for (i = 0; i < numPro; i++){
printf("Enter execution time for process %d: ", i);
scanf("%d", proTime + i);
sprintf(proNames[i], "p%d", i);
}
elemNum = 0;
//While a process remains active
while (numPro != 0) {
//Retrieves the element being worked with
elemNum = elemNum % numPro;
//Describe process working with
printf("Executing process %s\nStart time = %d\n", proNames[elemNum], time);
proTime[elemNum] -= quanTime;
//If process time complete, remove process
if (proTime[elemNum] <= 0){
removeProcess(proTime, elemNum);
removeProcessN(proNames, elemNum, numPro);
--numPro;
}
//Add amount of time with context time
time = time + quanTime + contTime;
elemNum++;
}
}
/**
*#param *array pointer to an array of integers
*#param elem int of the element to remove
* Removes an element 'elem' from the supplied integer array.
*/
void removeProcessN(char **array, int numElem, int elem) {
char *temparray[numElem - 1];
//Copy array to temparray except for elem to remove
int i;
for (i = 0; i < elem; i++) {
if (i == numElem) {
continue;
} else {
temparray[i] = array[i];
}
}
//End by setting the pointer of array to the temparray
array = temparray;
}
/**
*#param *array pointer to an array of integers
*#param elem int of the element to remove
* Removes an element 'elem' from the supplied integer array.
*/
void removeProcess(int *array, int elem) {
//Number of elements in the array
int numElem = sizeof(array) / sizeof(int);
int temparray[numElem - 1];
//Copy array to temparray except for elem to remove
int i;
for (i = 0; i < numElem; i++) {
if (i == elem) {
continue;
} else {
temparray[i] = array[i];
}
}
//End by setting the pointer of array to the temparray
array = temparray;
}
I know the segmentation fault is coming from sprintf. I am trying to simulate how an operating system would complete a process using round robin. I have tried using sprintf because that's what tutorials were saying online to use when trying to manipulate strings. The removeProcessN is just removing an index from the array proNames. I am mostly just concerned with the sprintf.
I have tried malloc when I do the sprintf but it would not even compile at that point. If someone could offer an explanation I'd be appreciative.
The problem here is that proNames is an array of pointers, but they are
uninitialized, so passing it to sprintf to write something, will crash. You
would have either use a double array or allocate memory with malloc. But as
you are only printing integers and the string representatuion of integers has a
maximal length, allocating memory with malloc will be more harder, because you
have to check that malloc doesn't return NULL, you have to free the memory
later, etc.
So I'd do:
char proNames[numPro][30]; // 28 characters for an int (usually 4 bytes long)
// should be more than enough
//Retrieves process time from user
for (i = 0; i < numPro; i++){
printf("Enter execution time for process %d: ", i);
scanf("%d", proTime + i);
sprintf(proNames[i], "p%d", i);
}
Your removeProcessN would need to change as well:
void removeProcessN(int numElem, int elem, int dim, char (*array)[dim]) {
for(int i = elem; i < numElem - 1; ++i)
strcpy(array[i], array[i+1]);
array[numElem - 1][0] = 0; // setting last element to empty string
}
Note that I moved the array argument at the last position, otherwise numElem
is not known and the compiler would return an error.
And now you can call it like this:
removeProcessN(elemNum, numPro, 30, proNames);
The 30 comes from the char proNames[numProp][30]; declaration.
I'd like to comment on the last line of your function removeProcessN:
//End by setting the pointer of array to the temparray
array = temparray;
That is not correct, first because temparray is local variable and ceases to
exist when the function returns. And array is local variable in the function,
so changing it doesn't affect anybody.
The alternative with memory allocation would look like this:
char *proNames[numPro];
//Retrieves process time from user
for (i = 0; i < numPro; i++){
printf("Enter execution time for process %d: ", i);
scanf("%d", proTime + i);
int len = snprintf(NULL, 0, "p%d", i);
proNames[i] = malloc(len + 1);
if(proNames[i] == NULL)
{
// error handling, free the previously allocated
// memory, and return/exit
}
sprintf(proNames[i], "p%d", i);
}
and removeProcessN:
void removeProcessN(char **array, int numElem, int elem) {
char *to_remove = array[elem];
for(int i = elem; i < numElem - 1; ++i)
array[i] = array[i+1];
free(to_remove);
array[numElem - 1] = NULL; // setting last element to NULL
// makes freeing easier as
// free(NULL) is allowed
}
And the way you originally called the removeProcessN would be OK.
If you eventually call removeProcessN for all processes, then all the memory
should be freed because removeProcessN frees it. If there are some elements
that remain in the array, then you have to free them later.
OP posted in the comments
My theory was that temparray would be a pointer to an array so I could just remove an index from the main array.
So when I say array = temparray, the pointer for array points to temparray. I know it worked for removeProcess. Is it different for strings?
The array = temparray also has no effect in removeProcess, array is still
a local variable and changing where it points to has no effect at all, because
you are changing a local variable only.
Besides the code is wrong:
int numElem = sizeof(array) / sizeof(int);
this only works for pure arrays, it does not work for pointers because
sizeof(array) returns you the size that a pointer of int needs to be stored.
Like the other function, you need to pass the site the array to the function.
If you say that this function worked, then just only by accident, because it
yields undefined behavior. By incorrectly calculating the number of elements,
temparray will have the wrong size, so here temparray[i] = array[i]; you may
access beyond the bounds which leads to undefined behaviour. Undefined behaviour
means that you cannot predict what is going to happen, it could be anything from
crashing to formatting your hard drive. Results that result from undefined
behaviour are useless.
And again array = temparray; just changes where the local variable array is
pointing, the caller of removeProcess doesn't see that.
The correct version would be:
int removeProcess(int *array, int elem, int numElem) {
if(array == NULL)
return 0;
// nothing to do if the elemnt to be removed is
// the last one
if(elem == numElem - 1)
return 1;
// overwriting the memory, because memory
// regions overlap, we use memmove
memmove(array + elem, array + elem + 1, numElem - elem - 1);
return 0;
}
So, to make it clear:
Let's look at this code:
void sum(int *array, size_t len);
{
int c[len];
array = c;
}
void bar(void)
{
int x[] = { 1, 3, 5 };
size_t len = sizeof x / sizeof *x;
sum(x, sizeof x / sizeof *x);
printf("x[0] = %d, x[1] = %d, x[2] = %d\n", x[0], x[1], x[2]);
}
sum has only a copy of the pointer you've passed in bar, so from bar's
point of view, sum changed the copy, so bar will print
x[0] = 1, x[1] = 3, x[2] = 5.
But if you want that the caller sees any change, then you to access through the
pointer:
void sum(int *array, size_t len)
{
int c[len];
for(size_t i = 0; i < len; ++i)
array[i] += 10;
array = c;
}
With this version bar would print x[0] = 11, x[1] = 13, x[2] = 15 and
and array = c will have no effect on bar.

Pointer values changes when using realloc() on pointer to pointer

I have to read from a file which has a unknown number of students records in it written in binary, then sort the students by their GPA and send to stdout.
Our sort function had to be like
void insertion_sort(Student **, int);
That's why I choose to use an pointer to a pointer to Student (probably not the best solution? I think I could have just sent an pointer to Student like this (&p_to_Student, n) ?)
The code is bellow, the problem is that when I print the first element of what p is pointing to (the first students name) I get gibberish, the other students are fine.
I checked the value of p, and it does change after realloc() is called, and because it's also the address of the first element of p (right?).
Also checked with Valgrind and it returns a bunch of errors about memory leaks!
The code runs fine when there is no realloc() call, also when I initialize p after I'm done reading the file. So it must be something to do with not using realloc() correctly.
Bonus question: is this a proper way to read an unknown number of data entries from a file?
#include <stdio.h>
#include <stdlib.h>
struct student {
char name[30];
char surname[30];
double GPA;
};
typedef struct student Student;
void insertion_sort(Student **arr, int n)
{
int i,j;
for (i=1; i<n; i++)
{
Student *tmp = arr[i];
for (j=i; j>0 && (tmp->GPA > arr[j-1]->GPA); j--)
arr[j] = arr[j-1];
arr[j] = tmp;
}
}
int main(int argc, char **argv)
{
FILE *in;
Student s, *arr, **p;
size_t ret;
int i = 1, n=0, c=2;
in = fopen(argv[1], "rb");
if (in == NULL)
return printf("Can't open file!\n"), 1;
arr = (Student*) malloc(c*sizeof(Student*));
p = (Student**) malloc(c*sizeof(Student*));
do
{
ret = fread(&s, sizeof(Student), 1, in);
if (ret)
{
if (n == c)
{
arr = (Student*) realloc(arr, (c*=2)*sizeof(Student));
p = (Student**) realloc(p, c*sizeof(Student*));
}
// when I print the value of pointer p
// the values is changed when realloc() is called
printf("p = %p\n", p);
arr[n] = s;
p[n] = arr+n;
n++;
}
} while (ret);
fclose(in);
// If I do this instead the program runs correctly
//p = (Student**) malloc(c*sizeof(Student));
//for (int i=0; i<n; i++)
//{
//p[i] = arr+i;
//}
insertion_sort(p, n);
for (i=0; i<n; i++)
{
printf("%2d. %-20s %-20s %7.2lf\n", i+1, p[i]->name,
p[i]->surname, p[i]->GPA);
}
free(arr);
free(p);
return 0;
}
realloc may change the pointer. That means all pointers into that pointer may become invalid. In your case, p holds pointers into arr.
Your problem is not that the value of p changes, but that the old values of p are no longer valid when the value of arr changes.
To illustrate (all pointer and size values are made up):
sizeof(stud) == 16;
allocate arr: arr == 0x00100000;
1st value: arr[0] = stud1; p[0] = &arr[0]; // 0x00100000
2nd value: arr[1] = stud2; p[1] = &arr[1]; // 0x00100010
reallocate arr: arr == 0x00200000;
old address of arr is no longer valid!
3rd value: arr[0] = stud1; p[2] = &arr[2]; // 0x00200020
Now your pointer array looks like this:
p[0] == 0x00100000 // no longer valid!
p[0] == 0x00100010 // no longer valid!
p[0] == 0x00200020 // okay
Because you need p only for your sorting, the approach you have commented out – to allocate p at one go before sorting – is better.
realloc is useful only if you don't now beforehand how big your array is, so you should use it as long as you are building the array. When you are done building the array and you can be sure that arr will stay the same you should create the array of pointers, p.

How to cycle through array without indexes in C?

I need to allocate an N sized array and assign it values, how can I do it without int indexes?
Here is the code I have so far but it doesn't do what I need:
#include <stdlib.h>
#include <stdio.h>
int main() {
int *array;
int n;
printf("Size of array: ");
scanf("%d", &n);
array = (int*) malloc(n*sizeof(int));
if (array == NULL) printf("Memory Fail");
for(; *array; array++)
{
printf("Store:\n");
scanf("%d", &n);
*array = n;
}
for(; *array; array++)
{
printf("Print: %d\n",*array);
}
free(array);
return 0;
}
thanks
for(; *array; array++); you should remove ; at the end
Number of iterations for this loop is undefined and you are going to lose a pointer
You should do something like this:
int *cur;
for(cur = array; cur < array+n; ++cur)
{
*cur = ...;
}
When you allocate the memory, you have no way to determine, in the memory, where it ends (unless you decide a convention and set a value somewhere, but anyway you would use n) .
In your case you have to use n to limit the array coverage (otherwise it is only limited by your computer capacity, and until it reaches an area where it does not have access: program crash). For instance (be careful not to overwrite n !)
int v;
int x = n;
int *ptr = array;
while (x--)
{
printf("Store:\n");
scanf("%d", &v);
*ptr++ = v;
}
x = n;
ptr = array;
while (x--)
{
printf("Print: %d\n",*ptr++);
}
You are using *array as your condition, which means the for loop should continue unless *array evaluates to false, which is only if *array == 0. You are actually invoking undefined behavior because you allocate array with malloc and are trying to dereference the pointer when the underlying data could be anything, since the data block has been uninitialized.
You still need some type of counter to loop with, in this case you allocated n items.
/* I'm using a C99 construct by declaring variables in the for initializer */
for (int i = 0; i < n; ++i)
{
/* In your original code you re-assign your counter 'n', don't do that otherwise you lost the size of your array! */
int temp;
printf("Store: \n");
scanf("%d", &temp)
array[i] = temp;
}
/* This is your second loop which prints the items */
for (int i = 0; i < n; ++i)
{
printf("%d\n", array[i]);
}
Also, do not manipulate the array pointer without keeping a copy of it. You can only do free on the pointer returned by malloc.
Using indexes is the same as manipulating the pointer, your professor is being ridiculous otherwise.
If you have an array int *a; then:
a[0] is equal to *a
a[1] is equal to *(a+1)
a[2] is equal to *(a+2)
So you can go through the array by doing arithmetic on the pointer.

Using malloc for allocation of multi-dimensional arrays with different row lengths

I have the following C code :
int *a;
size_t size = 2000*sizeof(int);
a = malloc(size);
which works fine. But if I have the following :
char **b = malloc(2000*sizeof *b);
where every element of b has different length.
How is it possible to do the same thing for b as i did for a; i.e. the following code would hold correct?
char *c;
size_t size = 2000*sizeof(char *);
c = malloc(size);
First, you need to allocate array of pointers like char **c = malloc( N * sizeof( char* )), then allocate each row with a separate call to malloc, probably in the loop:
/* N is the number of rows */
/* note: c is char** */
if (( c = malloc( N*sizeof( char* ))) == NULL )
{ /* error */ }
for ( i = 0; i < N; i++ )
{
/* x_i here is the size of given row, no need to
* multiply by sizeof( char ), it's always 1
*/
if (( c[i] = malloc( x_i )) == NULL )
{ /* error */ }
/* probably init the row here */
}
/* access matrix elements: c[i] give you a pointer
* to the row array, c[i][j] indexes an element
*/
c[i][j] = 'a';
If you know the total number of elements (e.g. N*M) you can do this in a single allocation.
The typical form for dynamically allocating an NxM array of type T is
T **a = malloc(sizeof *a * N);
if (a)
{
for (i = 0; i < N; i++)
{
a[i] = malloc(sizeof *a[i] * M);
}
}
If each element of the array has a different length, then replace M with the appropriate length for that element; for example
T **a = malloc(sizeof *a * N);
if (a)
{
for (i = 0; i < N; i++)
{
a[i] = malloc(sizeof *a[i] * length_for_this_element);
}
}
Equivalent memory allocation for char a[10][20] would be as follows.
char **a;
a=malloc(10*sizeof(char *));
for(i=0;i<10;i++)
a[i]=malloc(20*sizeof(char));
I hope this looks simple to understand.
The other approach would be to allocate one contiguous chunk of memory comprising header block for pointers to rows as well as body block to store actual data in rows. Then just mark up memory by assigning addresses of memory in body to the pointers in header on per-row basis. It would look like follows:
int** 2dAlloc(int rows, int* columns) {
int header = rows * sizeof(int*);
int body = 0;
for(int i=0; i<rows; body+=columnSizes[i++]) {
}
body*=sizeof(int);
int** rowptr = (int**)malloc(header + body);
int* buf = (int*)(rowptr + rows);
rowptr[0] = buf;
int k;
for(k = 1; k < rows; ++k) {
rowptr[k] = rowptr[k-1] + columns[k-1];
}
return rowptr;
}
int main() {
// specifying column amount on per-row basis
int columns[] = {1,2,3};
int rows = sizeof(columns)/sizeof(int);
int** matrix = 2dAlloc(rows, &columns);
// using allocated array
for(int i = 0; i<rows; ++i) {
for(int j = 0; j<columns[i]; ++j) {
cout<<matrix[i][j]<<", ";
}
cout<<endl;
}
// now it is time to get rid of allocated
// memory in only one call to "free"
free matrix;
}
The advantage of this approach is elegant freeing of memory and ability to use array-like notation to access elements of the resulting 2D array.
If every element in b has different lengths, then you need to do something like:
int totalLength = 0;
for_every_element_in_b {
totalLength += length_of_this_b_in_bytes;
}
return malloc(totalLength);
I think a 2 step approach is best, because c 2-d arrays are just and array of arrays. The first step is to allocate a single array, then loop through it allocating arrays for each column as you go. This article gives good detail.
2-D Array Dynamic Memory Allocation
int **a,i;
// for any number of rows & columns this will work
a = malloc(rows*sizeof(int *));
for(i=0;i<rows;i++)
*(a+i) = malloc(cols*sizeof(int));
malloc does not allocate on specific boundaries, so it must be assumed that it allocates on a byte boundary.
The returned pointer can then not be used if converted to any other type, since accessing that pointer will probably produce a memory access violation by the CPU, and the application will be immediately shut down.

Resources