Trouble visualizing the stack and heap - c

I apologize if this is too much code to post, I will delete this if that it is the case. My code below compiles and runs fine but I am unsure if I am allocating memory in the correct spots. Particularly, task 7 and 8. Task 7 should be an array of 10 pointers allocated on the
stack with each pointer referring to 10 unique instances allocated on the heap. Task 8 should be a single pointer allocated on the stack with the pointer referring to an array of 10 instances allocated on the heap. I feel like I have done task 7 and 8 backwards. As you can probably tell this is an assignment and I'm not looking for direct answers. I would just like to know if I'm on the right track for task 7 and 8.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
/* Task 1 -- add typedef and rename to Point3d */
typedef struct POINT_3D
{
int x_cord;
int y_cord;
int z_cord;
} Point3d;
/*Add function prototypes here*/
void init_Point1(Point3d* pt);
Point3d init_Point2(Point3d pt);
void PrintPoint1 (Point3d *pt);
void PrintPoint2(Point3d pt);
int main()
{
int i;
Point3d pt1;
/* Task 2 -- using proper operator give values (5,4,2) to pt1
and use the proper Print function to print it */
pt1.x_cord = 5;
pt1.y_cord = 4;
pt1.z_cord = 2;
printf("Printing Point3d:");
PrintPoint1(&pt1);
/*Task 3 -- Declare a pointer of type Point3d named ptr1*/
Point3d *ptr1;
/*Task 4 -- Allocate memory for ptr1 and initialize it by
calling init_Point1() function and use the proper Print function to print it */
ptr1 = (Point3d*) malloc(sizeof(Point3d));
init_Point1(ptr1);
printf("Printing Point3d:");
PrintPoint1(ptr1);
//Declaring second variable pt2
Point3d pt2;
/*Task 5 and 6 -- Compelete init_Point2 function and
call it with pt2 to create a point with random coordinates)
, use the proper Print function to print it*/
init_Point2 (pt2);
printf("Printing Point3d:");
PrintPoint2(pt2);
/************************************************/
/*************** Part 2 *************************/
/************************************************/
/* All three variables p1, p2, and p3 are intended to be used as *
* some form of array of the struct type declared above. */
Point3d p1[SIZE];
Point3d* p2[SIZE];
Point3d* p3;
printf ("Calling init_Point1()\n");
for (i = 0 ; i < SIZE; ++i)
{
printf ("For position %d\n", i);
init_Point1 (&p1[i]);
PrintPoint1(&p1[i]);
//PrintPoint2(p1[i])
}
/*Task 7 -- Repeat the same steps for array p2, you must call a
proper init function and display the results by calling Print function */
/***********************************/
/* p2 : Declare, Initialize, Print */
/***********************************/
printf ("Calling init_Point1()\n");
for ( i = 0; i < SIZE; i++)
{
p2[i] = (Point3d*) malloc(sizeof(Point3d));
printf ("For position %d\n", i);
init_Point1 (p2[i]);
PrintPoint1 (p2[i]);
}
/* Task 8 -- p3 is a single pointer that must refer to an array of 10 instances
allocated on the heap. Repeat the previous steps for p3 by initializing and
printing using proper functions*/
/***********************************/
/* p3 : Declare, Initialize, Print */
/***********************************/
p3 = (Point3d*) malloc(sizeof(Point3d)*SIZE);
printf ("Calling init_Point1()\n");
for ( i = 0; i < SIZE; i++)
{
printf ("For position %d\n", i);
init_Point1 (&p3[i]);
PrintPoint1 (&p3[i]);
}
return 0;
}
/************************/
/* function definitions */
/************************/
void init_Point1 (Point3d *pt)
{
pt->x_cord = rand() % 100;
pt->y_cord = rand() % 1000;
pt->z_cord = rand() % 100;
}
/* Task 5 - write init_Point2() function definition */
Point3d init_Point2 (Point3d pt)
{
pt.x_cord = rand() % 100;
pt.y_cord = rand() % 1000;
pt.z_cord = rand() % 100;
return pt;
}
void PrintPoint1 (Point3d *pt)
{
printf("\t(x %d , y %d , z %d ) \t", pt->x_cord, pt->y_cord, pt->z_cord);
printf("\n");
}
void PrintPoint2 (Point3d pt)
{
printf("\t(x %d , y %d , z %d ) \t", pt.x_cord, pt.y_cord, pt.z_cord);
printf("\n");
}

Related

How do i use a pointer in C to return a value?

I am trying to make a pointer P return to me the index of the first occurrence of given number in an array using count function that i wrote (J's job is to return the number of occurrences), the idea here is that im trying to write a function that returns 2 values instead of 1 (P returns index of first occurrence and J returns its number) in such way:
int count(int h[],int *p,int size,int d)
{
int j=0;
int bool = 0;
for(int i=0; i<size ;i++)
{
if(h[i]==d && bool == 0)
{
j++;
bool = 1;
p = &i;
}
else if(h[i]==d)
j++;
}
if(bool==0)
{
j=-1;
*p=-1;
return j;
}
else
return j;
}
void main ()
{
int j;
int *p = NULL;
int h[] = {1,2,3,4,5,1,1,3,4};
j = count(h, p , sizeof(h)/sizeof(int) , 1);
printf("%d %d", *p,j);
}
I am fully aware aware that instead of using int *p, i can simply use P and pass its address in such way:
void printarray(int h[],int size){
for(int i=0;i < size ;i++)
{
printf(" %d ",h[i]);
}
printf("\n");
}
int count(int h[],int *p,int size,int d)
{
int j=0;
int bool = 0;
for(int i=0; i<size ;i++)
{
if(h[i]==d && bool == 0)
{
j++;
bool = 1;
*p = i;
}
else if(h[i]==d)
j++;
}
if(bool==0)
{
j=-1;
*p=-1;
return j;
}
else
return j;
}
void main ()
{
int j;
int p;
int h[] = {1,2,3,4,5,1,1,3,4};
printarray(h,sizeof(h)/sizeof(int));
j = count(h, &p , sizeof(h)/sizeof(int) , 1);
printf("%d %d", p,j);
}
What Really intrigues me is that why does it show a segmentation fault when using the pointer ? or am i just wrong about using a pointer in the first place and i should pass the address of an int in case i want my function to return 2 values for me ?
That which is a pointer has to point to something. So when you wrote int *p = NULL; you didn't give it somewhere to point. You could have done int n; int *p = &n; and proceed to pass p.
But it gets bumpy from here. You tried to write p = &i; inside the function. While that's completely valid code, from that point, assigning to *p will mess up your loop control function. This is not what you want. In the "I know I can" section you have the more reasonable *p = i;.
I'm guessing you want to know how to pass something allocated in the function to its caller. You can in fact do this; there's standard library functions designed for this task. You can in fact write
int count(int h[],int **p,int size,int d)
{
int j=0;
int bool = 0;
for(int i=0; i<size ;i++)
{
if(h[i]==d && bool == 0)
{
j++;
bool = 1;
*p = malloc(sizeof(int));
**p = i;
}
else if(h[i]==d)
j++;
}
if(bool==0)
{
j=-1;
return j;
}
else
return j;
}
void main ()
{
int j;
int *p = NULL;
int h[] = {1,2,3,4,5,1,1,3,4};
j = count(h, &p , sizeof(h)/sizeof(int) , 1);
if (p) {
printf("%d %d", *p,j);
free(p);
} else {
printf("(no index) %d", j);
}
}
So what happened here is we have a pointer in main() that is initialized to point nowhere, may or may not be set in count to point to the index. If nothing is found, p will still point to NULL (nowhere). The function malloc() returns the newly allocated memory so that p has somewhere to point; and the function free returns it.
** is a simple idea that gives people headaches. Since a pointer is * we add another * when we want a pointer to a pointer, so we can change that pointer. Just don't ask how deep you can go. The answer is don't try. Two happens a lot; three requires a good justification, and more than three is almost never done. More than two really is a headache and nobody wants headaches on their headaches. The limit is way higher. Nobody goes there.
It probably seems rather pointless, and it is. malloc() is used to allocate entire arrays in the function (whose size isn't known until runtime) and return them to the caller. A single int just isn't worth managing like this (the pointer is bigger than it is), but for an array it makes sense. So much that in big programs, almost everything is on the heap; unlike the small programs everybody starts with where almost everything is on the stack (local variables are on the stack).
You thinking about what you want to do correctly, but you are over complicating how to do it a bit. Instead of all the if ... else ... statements, what if you just used a flag like what you call bool (but let's rename it to something that won't conflict with the type from stdbool.h), call it first_set instead. Initialize it with a value of 0 (false) to begin with, and then when you find the first occurrence, update first_set = 1;
If you step back and thing of what your primary check needs to be, all you are really worried about locating in your array is the first, and all remaining indexes where the given value (let's call val instead of d) is equal to the array element. (and since a count, a length and an array index cannot be negative, let's choose size_t as the type for the positive counting values). To track the number of occurrences, let's use occurs as the variable (helps keep things readable in long programs)
So all you really want to do is loop over each element in your array and check if the current element is equal to the value you are searching for. That is the primary concern from which all other actions can be taken. You can keep your parameters in the order you like, but I find it easier to think about the function (1) taking an array, (2) of a given number of elements, where I will find (3) the first occurrence or (4) a given value. (whatever makes sense to you, but is also readable to whoever works on your code later) So with a slight tweak of the ordering (at least for my old eyes), you could set up your function to loop over each element and locate all of the occurrences of a given value as:
size_t arr_occurrences (int *a, size_t nelem, size_t *first, int val)
{
int first_set = 0; /* flag if 1st occurrence set */
size_t occurs = 0; /* total no. of occurrences */
for (size_t i = 0; i < nelem; i++) { /* loop over each element */
if (a[i] == val) { /* is it equal to val? */
...
occurs += 1; /* increment no. of occurrences */
}
}
return occurs; /* return total number of occurrences */
}
The only thing left to add is how to set the first occurrence. While you talk in terms of locating the "address" of the first occurrences in the function, what I think you really mean is locating the "index" of the first occurrence within the array. You can convert the index back to an address in the calling function and not have to worry about passing something that can hold the address (which would require passing a pointer-to-pointer rather than a pointer-to int)
So the first time the test of a[i] == val tests true, you want to capture the index and save it, ensuring you don't change it for any of the other times a[i] == val tests true during your loop. You have your first_set flag that is currently set to 0 (false), so all you really need to capture your first index in the array where val occurs is:
if (!first_set) { /* if first not set */
*first = i; /* update value at address of first */
first_set = 1; /* set first_set flag true */
}
If you put that in place of the ... placeholder in the function above, you would have:
size_t arr_occurrences (int *a, size_t nelem, size_t *first, int val)
{
int first_set = 0; /* flag if 1st occurrence set */
size_t occurs = 0; /* total no. of occurrences */
for (size_t i = 0; i < nelem; i++) { /* loop over each element */
if (a[i] == val) { /* is it equal to val? */
if (!first_set) { /* if first not set */
*first = i; /* update value at address of first */
first_set = 1; /* set first_set flag true */
}
occurs += 1; /* increment no. of occurrences */
}
}
return occurs; /* return total number of occurrences */
}
Short and sweet, no else needed, just a check of your flag first_set and if it isn't set, capture the index and set first_set true so you don't change in during the remainder of your loop. Your function makes the index of the first occurrence of val available back in the calling function by updating the value at the address held by the pointer first. The function returns the total number of occurrences for val in your array so it too is available to the caller. (with a slight change of type to size_t)
(another benefit of using size_t on platforms where size_t is larger than int is your array (or allocated block) can hold more than INT_MAX values and your code will still work without risk of integer overflow if a count exceeds what can be represented by an int)
Putting it altogether in a short example that creates an array of 100 elements holding random values from -10 to 10 and then chooses the value to find by choosing a random value in that range, you could check that all works as expected as follows:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NELEM 100 /* if you need a constant, #define one (or more) */
#define PERROW 10
#define LO_LIM -10
#define HI_LIM 10
int rand_in_range (int lowlim, int highlim)
{
return rand() % (highlim - lowlim + 1) + lowlim;
}
void arr_fill_rand (int *a, size_t nelem, int lowlim, int highlim)
{
for (size_t i = 0; i < nelem; i++)
a[i] = rand_in_range (lowlim, highlim);
}
void arr_prn (int *a, size_t nelem, const char* fmt)
{
const char *format = fmt != NULL ? fmt : " %d";
for (size_t i = 0; i < nelem; i++) {
if (i && i % PERROW == 0)
putchar ('\n');
printf (format, a[i]);
}
putchar ('\n');
}
size_t arr_occurrences (int *a, size_t nelem, size_t *first, int val)
{
int first_set = 0; /* flag if 1st occurrence set */
size_t occurs = 0; /* total no. of occurrences */
for (size_t i = 0; i < nelem; i++) { /* loop over each element */
if (a[i] == val) { /* is it equal to val? */
if (!first_set) { /* if first not set */
*first = i; /* update value at address of first */
first_set = 1; /* set first_set flag true */
}
occurs += 1; /* increment no. of occurrences */
}
}
return occurs; /* return total number of occurrences */
}
int main (void) {
int arr[NELEM] = {0}, /* array of NELEM set all zero */
val = 0; /* value to find */
size_t first = 0, /* index of first occurrence */
occurs = 0; /* total no. of occurrences */
srand (time(NULL)); /* seed random number generator */
val = rand_in_range (LO_LIM, HI_LIM); /* random in LO to HI (inclusive) */
arr_fill_rand (arr, NELEM, LO_LIM, HI_LIM); /* fill with random values in range */
arr_prn (arr, NELEM, " % 3d");
occurs = arr_occurrences (arr, NELEM, &first, val); /* get occurrences of val */
printf ("\n%d occurs first in array of %d " /* output results */
"elements ranging from %d to %d at:\n"
" index : %zu\n"
" address : %p\n"
"and occurs a total of %zu times.\n",
val, NELEM, LO_LIM, HI_LIM,
first, (void*)&arr[first], occurs);
}
(note: you never need more than one call to printf() (or fputs() or puts()) to provide on block of output, regardless of the number of lines it contains. You can keep things readable in longer output by breaking the string up into adjacent strings (newlines and other whitespace between them is ignored) and the compiler with create a single string to output from all adjacent string literals)
Example Use/Output
The program outputs the array and then outputs the results with the index of the first occurrence (and it's actual address if that is what you wanted) along with the total number of times the value of interest was found:
$ ./bin/arr_rand_1st_occ+count
3 -10 2 10 2 -9 4 5 -3 7
-4 -6 10 -4 8 -5 8 5 -10 10
10 6 -3 2 -5 1 1 8 10 -1
6 0 -1 -5 -1 10 -6 -10 4 1
5 -10 6 5 -4 1 8 -8 -4 8
-9 -7 2 -4 5 7 5 -7 3 4
2 -4 -6 10 1 1 9 5 0 0
-7 -6 -2 9 7 3 -2 4 3 4
2 4 5 -9 8 -3 6 2 0 -2
-6 -10 4 -2 8 -8 7 6 5 -4
8 occurs first in array of 100 elements ranging from -10 to 10 at:
index : 14
address : 0x7ffea2fb5938
and occurs a total of 7 times.
The array is output with 10 values PERROW to make things easier to read. Remember when confirming the results, arrays are zero-indexed in C.
Last note is unless you are programming in a freestanding environment (without the benefit of any OS), the allowable declarations for main for are int main (void) and int main (int argc, char *argv[]) (which you will see written with the equivalent char **argv). See: C11 Standard - ยง5.1.2.2.1 Program startup(p1). See also: What should main() return in C and C++?
In a freestanding environment (such as programming on a microcontroller) without the benefit of an operating-system, the name and type of the function called at program startup are implementation-defined. See: C11 Standard - 5.1.2.1 Freestanding environment
Look things over and let me know if you have further questions.
Your program behaviour is undefined because it end up dereferencing a NULL pointer here:
int *p = NULL;
int h[] = {1,2,3,4,5,1,1,3,4};
j = count(h, p , sizeof(h)/sizeof(int) , 1);
printf("%d %d", *p,j);
^^
|
Dereferencing p which is a NULL pointer
The way you are passing the p pointer from main() function to count() function, you are passing NULL. That means, in context of your program, this
j = count(h, p , sizeof(h)/sizeof(int) , 1);
is equivalent to this
j = count(h, NULL , sizeof(h)/sizeof(int) , 1);
The count() function parameter p will receive NULL as argument i.e. it's equivalent to p = NULL (where p is count() function parameter).
Whatever you assign to p in count() function, you are actually modifying a local variable of count() function. No changes are going to reflect in pointer variable p of main() function and it will remain a NULL pointer.
Now, lets come to the count() function.
In this snip of code of count() function:
for(int i=0; i<size ;i++)
{
if(h[i]==d && bool == 0)
{
j++;
bool = 1;
p = &i;
}
else if(h[i]==d)
j++;
}
the scope and life of loop variable i is within the for loop block. Once, the loop exit the lifetime of i is ended. JFYI - accessing an object outside of its lifetime is undefined behaviour. So, if p hold &i and out of loop body if your program access p then it will lead to undefined behaviour. Also, *p=-1; statement in count() will also lead to undefined behaviour because, in count() function p will be a NULL pointer if bool==0.
Remember, if a function is passing a pointer to another function as a argument and expecting that function to modify the value of pointer, which it receive as parameter, then the pointer should be pointing to a valid memory location before the calling function access and modify it's memory contents or the caller function should pass address of pointer as argument and let the calling function allocate memory dynamically to it so that it should be accessible from the caller function as well (which is main() function, in your case).
There are couple ways to achieve this.
Method I:
Pass a valid memory location to calling function.
Either pass address of a local variable of caller function as argument (this is same as your second code snippet)
int main (void) {
int j;
size_t res = 0;
size_t *p = &res; // p is pointing to res variable
int h[] = {1, 2, 3, 4, 5, 1, 1, 3, 4};
int num = 1;
j = count (h, p, sizeof (h) / sizeof (int), num);
if (j != -1) {
printf ("%zu %d", *p, j);
} else {
printf ("%d not found\n", num);
}
return 0;
}
Or allocate memory to pointer in caller function and pass it
int main (void)
{
int j;
size_t *p = NULL;
int h[] = {1, 2, 3, 4, 5, 1, 1, 3, 4};
int num = 1;
p = malloc (sizeof (size_t));
if (p == NULL) {
fprintf (stderr, "Failed to allocate memory");
exit (EXIT_FAILURE); // or whatever you want to do in case of allocation failure
}
j = count (h, p, sizeof (h) / sizeof (int), num);
if (j != -1) {
printf ("%zu %d", *p, j);
} else {
printf ("%d not found\n", num);
}
free(p);
return 0;
}
and the count() function implementation for both the above cases:
int count (int h[], size_t *p, size_t size, int d) {
int j = 0;
for (size_t i = 0; i < size ; ++i) {
if(h[i] == d) {
if (j == 0) {
*p = i;
}
++j;
}
}
return j == 0 ? -1 : j;
}
Method II:
Pass the address of p and dynamically allocate memory to p in count() function before accessing it. Note that, objects with allocated storage duration live until they are destroyed by a call to free(). So, if count() function allocates memory to a pointer, whose address passed as argument to count() function from main() function, then that memory will be accessible in main() function as well via pointer variable p.
#include <stdio.h>
#include <stdlib.h>
int count (int h[], size_t **p, size_t size, int d) {
int j = 0;
for(size_t i = 0; i < size ; ++i) {
if(h[i] == d) {
if ((j == 0) && (p != NULL)) {
*p = malloc (sizeof (size_t));
if (p == NULL) {
fprintf (stderr, "Failed to allocate memory");
exit (EXIT_FAILURE);
}
**p = i;
}
++j;
}
}
return j == 0 ? -1 : j;
}
int main (void) {
int retval;
size_t *p = NULL;
int h[] = {1, 2, 3, 4, 5, 1, 1, 3, 4};
int num = 3;
retval = count (h, &p, sizeof (h) / sizeof (int), num);
if (retval != -1) {
printf ("%zu %d\n", *p, retval);
} else {
printf ("%d not found\n", num);
}
// free memory once you are done with it
if (p != NULL) {
free (p);
}
return 0;
}
Additional:
Using void as return type of main function is not as per standards. The return type of main function should be int.
You are trying to return pointer pointing to a place which will be no longer valid once the loop completed it's execution, either declare i outside for or don't use the pointer part, as dereferencing a null pointer is illegal, also, you get segmentation fault when you try to access memory you have no business with and no permission to read or write, in this case, pointing to a memory location which is out of scope.
Instead of returning a pointer,simply create a local array of same type in the function, first index for first occurence of the given number, and second index for the total occurence, and return the array but make sure the return type should be pointer of same type.
edit: thanks Mr. Joshua, for pointing out the mistake.

Having trouble with memory leak

I am trying to generate a Fibonacci sequence by allocating space for 2 elements, so I need my array a[0] and a[1] to be constantly updated until it outputs 89 as the final number.
This is my code:
#include <stdio.h>
#include <stdlib.h>
void fib2(int* a);
int main()
{
int *pointer;
//allocates space for 2 elements for pointer
pointer = (int*)malloc(2 * sizeof(int*));
//prints first two fibonacci values
printf("0 1 ");
//calls fib2 func and apsses pointer into it
fib2(pointer);
//frees pointer memory
free(pointer);
printf("\n");
return 0;
}
//generates fibonacci sequence
void fib2(int* a)
{
int i;
//allocates space for 2 elements
a = (int*)malloc(2 * sizeof(int*));
//initial fibonacci array initialized
a[0] = 0;
a[1] = 1;
//generates and calculates fibonacci sequence and prints
for(i = 2; i < 12; i++)
{
a[i] = a[i - 1] + a[i - 2];
printf("%d ", a[i]);
}
}
I tried freeing of a[] by doing free(a); but it outputs to the console like this
**edit this is the valgrind output
There are a number of problems.
Problem 1 Wrong malloc
int *pointer;
//allocates space for 2 elements for pointer
pointer = (int*)malloc(2 * sizeof(int*));
^^^^^^^^^^^^
The sizeof should be sizeof(int) as you want to allocate space for a number (2) int. Besides that you don't need the cast. A better way to write this is:
pointer = malloc(2 * sizeof *pointer);
Problem 2 You never use pointer for any thing
You do pass its value to fib2 so that its value goes into variable a. However, immediately after you do:
a = (int*)malloc(2 * sizeof(int*)); // also sizeof wrong again
so you actually overwrite whatever value that passed. Your call of fib2 could just as well be:
fib2(NULL);
In other words: Don't do malloc both in main and in fib2. Select one place.
Problem 3 The memory in malloc'ed in fib2 are never free'ed
Your current code leaks memory because fib2 doesn't end with code like: free(a);
Problem 4 You allocate too little memory
Obviously you want 12 elements in the integer array but you only allocate ! Change code to be:
a = malloc(12 * sizeof *a);
Putting things together it could look:
#include <stdio.h>
#include <stdlib.h>
void fib2(int* a, int n);
#define NUMBERS_TO_CALCULATE 12
int main()
{
int *pointer;
//allocates space for NUMBERS_TO_CALCULATE elements for pointer
pointer = malloc(NUMBERS_TO_CALCULATE * sizeof *pointer);
if (pointer == NULL) exit(1);
//calls fib2 func and apsses pointer into it
fib2(pointer, NUMBERS_TO_CALCULATE);
// ... use pointer for other things ...
//frees pointer memory
free(pointer);
return 0;
}
//generates fibonacci sequence
void fib2(int* a, int n)
{
int i;
if (n < 2) return;
//initial fibonacci array initialized
a[0] = 0;
a[1] = 1;
//prints first two fibonacci values
printf("0 1 ");
//generates and calculates fibonacci sequence and prints
for(i = 2; i < n; i++)
{
a[i] = a[i - 1] + a[i - 2];
printf("%d ", a[i]);
}
printf("\n");
}
Note: If you don't want to use pointer for other things in main, I'll suggest that you move the malloc and free into fib2
Edit based on comments from OP
In comments OP tells about a number of restriction like:
Must use malloc
Only allowed to malloc 2 integers (I assume this also means that local variables are not allowed in fib2)
Function prototype must be void fib2(int* a)
Must print values less or equal 89
With those restrictions the program could look:
#include <stdio.h>
#include <stdlib.h>
void fib2(int* a);
int main()
{
int *pointer;
//allocates space for 2 integer elements for pointer
pointer = malloc(2 * sizeof *pointer);
if (pointer == NULL) exit(1);
//initialize fibonacci start values
pointer[0] = 0;
pointer[1] = 1;
//calls fib2 func and apsses pointer into it
fib2(pointer);
//frees pointer memory
free(pointer);
return 0;
}
//generates fibonacci sequence
void fib2(int* a)
{
//prints first two fibonacci values
printf("%d %d ", a[0], a[1]);
//generates and calculates fibonacci sequence and prints
while(a[1] < 89)
{
a[1] = a[1] + a[0]; // Calculate next number and save in a[1]
printf("%d ", a[1]); // Print it
a[0] = a[1] - a[0]; // Calculate the number for a[0]
}
printf("\n");
}

Valgrind Invalid read of size 4 segfault

For an project assignment, I have this following variable from an prototype function which is not allocated.
int **suff;
This variable will receive a pointer to an array (int *) from a function which will generated an array of (int) from a FILO list (file).
(p is just a content structure, p->suff is a file)
int t = file_size(p->suff);
/* Prototype of file_tabint is
* int * file_tabint(file *p, int * psize)
*/
// Assign the generated array to the *suff)
*suff = file_tabint(p->suff, &t);
Now, when I want to print the array, valgrind raise a "invalid read of size 4"
for (int i = 0; i < t; i++) {
printf("%d -- ", *suff[i]);
}
My question is, what I did wrong in order to access to the int value of the array?
Note : I can't change the int **suff
The problem is *suff[i]. The way operator precedence works, that does suff[i] first and then dereferences whatever it finds there. You want to do it the other way round, so add brackets:
for (int i = 0; i < t; i++) {
printf("%d -- ", (*suff)[i]);
}

C - pointing members of array of struct into another array ( no duplicate struct data just point to it )

I have two identical arrays of struct , one in reverse order.
The problem is that i don't want duplicate the same data into the two arrays , i would a reversed array with elements pointing elements of the first array in a way that i can edit the members of struct of first array or from the reversed array taking effect in both.
you can view the source and run it online here https://onlinegdb.com/SJbepdWxS
#include <stdio.h>
typedef struct point{
int id;
float x,y,z;
} point;
void printPoints(point *pts,int len){
int i = 0;
while (pts !=NULL && i < len){
printf("id %d x %f y%f z %f\n",pts->id,pts->x,pts->y,pts->z);
pts++;
i++;
}
}
void translatePoints(point *pts,int len,float t){
int i = 0;
while (pts !=NULL && i < len){
pts->x = pts->x + t;
pts->y = pts->y + t;
pts->z = pts->z + t;
pts++;
i++;
}
}
void reversePoints(point *pts, int len, point *rev){
int i = 0;
int j = len;
while (i < len){
j=len-i-1;
rev[j]=pts[i];
i++;
}
}
int main()
{
int i;
int t1=200;
int t2=300;
int len=3;
point points[len];
point rev_points[len];
for(i=0; i<len ; i++){
points[i].id=i;
points[i].x=10+i;
points[i].y=20+i;
points[i].z=30+i;
}
//point * pts = points;
printf("\nprint points \n\n");
printPoints(points,len);
printf("\ntranslate points %d...\n\n",t1);
translatePoints(points,len,t1);
printf("\nprint points\n\n");
printf("\nreverse points to rev_points\n");
reversePoints(points,len,rev_points);
printf("\nprint rev_points \n\n");
printPoints(rev_points,len);
printf("\ntranslate rev_points %d...\n\n",t2);
translatePoints(rev_points,len,t2);
printf("\nprint rev_points\n\n");
printPoints(rev_points,len);
printf("\nprint points\n\n");
printPoints(points,len);
return 0;
}
I expect that struct values of both arrays change when i change value in one of the two array.
But changing values of struct in the first array , the second array not changes and the other way around.
One way to look at this is a set of points and two permutations on the set. This sets up a points array, which is used as a set, and forward_points and reverse_points as arrays of pointers to the point array that we are going to use as permutations.
#include <stdio.h>
struct Point {
int id;
float x,y,z;
};
/* Print a point. */
static void printPoint(struct Point *point) {
printf("id %d x %f y%f z %f\n",point->id,point->x,point->y,point->z);
}
/* These print out an array of pointers to point. */
static void printPointsRef(struct Point **ref, int len) {
struct Point **end = ref + len;
while(ref < end) printPoint(*(ref++));
}
/* This translates all the `pts` up to `len` by `(1,1,1)*t`. */
static void translatePoints(struct Point *pts, int len, float t) {
struct Point *end = pts + len;
while(pts < end) {
pts->x = pts->x + t;
pts->y = pts->y + t;
pts->z = pts->z + t;
pts++;
}
}
/* Helper function to `main`. */
static void printPoints(struct Point **forward_points,
struct Point **reverse_points, int len) {
printf("print points\nprint points forward:\n");
printPointsRef(forward_points,len);
printf("print points reverse:\n");
printPointsRef(reverse_points,len);
printf("\n");
}
int main(void)
{
const int len = 3;
/* This is the actual points structure. */
struct Point points[len];
/* These are arrays of pointers to points; they are
permutations of `points`. */
struct Point *forward_points[len], *reverse_points[len];
int i;
const int t1=200;
for(i=0; i<len; i++) {
/* Initialise element `i` of `points`. */
points[i].id=i;
points[i].x=10+i;
points[i].y=20+i;
points[i].z=30+i;
/* Initialise element `i` of `forward_points`
to point to `points[i]`, and `backward_points`
to point the other way (it doesn't matter that
the backwards points are uninitialised, they
will be.) */
forward_points[i] = &points[i];
reverse_points[i] = &points[len - 1 - i];
}
printPoints(forward_points, reverse_points, len);
/* Translation is a vector space operation and doesn't
care about order; we just do it on the original points. */
printf("translate points %d...\n\n",t1);
translatePoints(points,len,t1);
printPoints(forward_points, reverse_points, len);
return 0;
}
Of course, there is no integrity constraints on the pointers; nothing stopping one from pointing at anything, null, the same elements, or anything else.
I added an other struct with one element that is a pointer
typedef struct ptr_point{
point * p;
} ptr_point;
I edited the function reversePoints
void reversePoints(point *pts, int len, ptr_point *rev){
// This function is used only to test pointers
int i = 0;
int j = len;
while (i < len){
j=len-i-1;
rev[j].p = &pts[i];
i++;
}
}
and added another function to print ptr_points
void printPtrPoints(ptr_point *pts,int len){
int i = 0;
while (i < len){
printf("id %d x %f y%f z %f\n",pts->p->id,pts->p->x,pts->p->y,pts->p->z);
pts++;
i++;
}
}
and declaring the second array as ptr_point array
ptr_point rev_points[len];
In conclusion : now data in the second array are not replicated but pointing to element structure of the first array.
The need to not replicate data arise in presence of millions of coordinate points that if replicate more than one time , sorting it for example by x, y, z and so on , occupe much memory with the difficulty of managing .
This fix however forces me to use structures->type in order to change the access mode to read or set values.
I don't know if this is the best solution but it has solved the problem for not duplicate the data.
you can run the source with fixes here: https://onlinegdb.com/SknP_i-eS
Thank you all for the advice.

C pthread Segmentation fault

so I was trying to make a GPGPU emulator with c & pthreads but ran into a rather strange problem which I have no idea why its occurring. The code is as below:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <assert.h>
// simplifies malloc
#define MALLOC(a) (a *)malloc(sizeof(a))
// Index of x/y coordinate
#define x (0)
#define y (1)
// Defines size of a block
#define BLOCK_DIM_X (3)
#define BLOCK_DIM_Y (2)
// Defines size of the grid, i.e., how many blocks
#define GRID_DIM_X (5)
#define GRID_DIM_Y (7)
// Defines the number of threads in the grid
#define GRID_SIZE (BLOCK_DIM_X * BLOCK_DIM_Y * GRID_DIM_X * GRID_DIM_Y)
// execution environment for the kernel
typedef struct exec_env {
int threadIdx[2]; // thread location
int blockIdx[2];
int blockDim[2];
int gridDim[2];
float *A,*B; // parameters for the thread
float *C;
} exec_env;
// kernel
void *kernel(void *arg)
{
exec_env *env = (exec_env *) arg;
// compute number of threads in a block
int sz = env->blockDim[x] * env->blockDim[y];
// compute the index of the first thread in the block
int k = sz * (env->blockIdx[y]*env->gridDim[x] + env->blockIdx[x]);
// compute the index of a thread inside a block
k = k + env->threadIdx[y]*env->blockDim[x] + env->threadIdx[x];
// check whether it is in range
assert(k >= 0 && k < GRID_SIZE && "Wrong index computation");
// print coordinates in block and grid and computed index
/*printf("tx:%d ty:%d bx:%d by:%d idx:%d\n",env->threadIdx[x],
env->threadIdx[y],
env->blockIdx[x],
env->blockIdx[y], k);
*/
// retrieve two operands
float *A = &env->A[k];
float *B = &env->B[k];
printf("%f %f \n",*A, *B);
// retrieve pointer to result
float *C = &env->C[k];
// do actual computation here !!!
// For assignment replace the following line with
// the code to do matrix addition and multiplication.
*C = *A + *B;
// free execution environment (not needed anymore)
free(env);
return NULL;
}
// main function
int main(int argc, char **argv)
{
float A[GRID_SIZE] = {-1};
float B[GRID_SIZE] = {-1};
float C[GRID_SIZE] = {-1};
pthread_t threads[GRID_SIZE];
int i=0, bx, by, tx, ty;
//Error location
/*for (i = 0; i < GRID_SIZE;i++){
A[i] = i;
B[i] = i+1;
printf("%f %f\n ", A[i], B[i]);
}*/
// Step 1: create execution environment for threads and create thread
for (bx=0;bx<GRID_DIM_X;bx++) {
for (by=0;by<GRID_DIM_Y;by++) {
for (tx=0;tx<BLOCK_DIM_X;tx++) {
for (ty=0;ty<BLOCK_DIM_Y;ty++) {
exec_env *e = MALLOC(exec_env);
assert(e != NULL && "memory exhausted");
e->threadIdx[x]=tx;
e->threadIdx[y]=ty;
e->blockIdx[x]=bx;
e->blockIdx[y]=by;
e->blockDim[x]=BLOCK_DIM_X;
e->blockDim[y]=BLOCK_DIM_Y;
e->gridDim[x]=GRID_DIM_X;
e->gridDim[y]=GRID_DIM_Y;
// set parameters
e->A = A;
e->B = B;
e->C = C;
// create thread
pthread_create(&threads[i++],NULL,kernel,(void *)e);
}
}
}
}
// Step 2: wait for completion of all threads
for (i=0;i<GRID_SIZE;i++) {
pthread_join(threads[i], NULL);
}
// Step 3: print result
for (i=0;i<GRID_SIZE;i++) {
printf("%f ",C[i]);
}
printf("\n");
return 0;
}
Ok this code here runs fine, but as soon as I uncomment the "Error Location" (for loop which assigns A[i] = i and B[i] = i + 1, I get snapped by a segmentation fault in unix, and by these random 0s within C in cygwin. I must admit my fundamentals in C is pretty poor, so it may be highly likely that I missed something. If someone can give an idea on what's going wrong it'd be greatly appreciated. Thanks.
It works when you comment that because i is still 0 when the 4 nested loops start.
You have this:
for (i = 0; i < GRID_SIZE;i++){
A[i] = i;
B[i] = i+1;
printf("%f %f\n ", A[i], B[i]);
}
/* What value is `i` now ? */
And then
pthread_create(&threads[i++],NULL,kernel,(void *)e);
^
So pthread_create will try to access some interesting indexes indeed.

Resources