C Pointers and Access Violation Read Location - c

I'm new to C and still learning about pointers. I was just testing my understanding of pointers by trying to simulate appending to an array when I got an Access Violation Read Loaction error when using printf. This is the code:
#include <stdio.h>
#include <stdlib.h>
int arraySize(int *arrayToSize);
void changeAll(int ***a1PtrPtrPtr, int nToAdd){
int *bPtr = (int *)malloc((arraySize(**a1PtrPtrPtr) + 1) * sizeof(int));
int i = 0;
while (*(**a1PtrPtrPtr + i) != -1){
bPtr[i] = *(**a1PtrPtrPtr + i);
i++;
}
bPtr[i] = nToAdd; i++;
bPtr[i] = -1;
*a1PtrPtrPtr = &bPtr;
}
int main(void){
int a[4] = { 1, 2, 3, -1 };
int *aPtr = a;
int **aPtrPtr = &aPtr;
int ***aPtrPtrPtr = &aPtrPtr;
int n = 4;
changeAll(aPtrPtrPtr, n);
int counter = 0;
while (counter < 5){
int temp = *(*aPtrPtr + counter);
printf("%d is %d", counter, temp );
counter++;
}
return 0;
}
int arraySize(int *arrayToSize){
int sizeTemp = 0;
int i = 0;
while (arrayToSize[i] != -1){
sizeTemp++;
i++;
}
sizeTemp++;
return sizeTemp;
}
I get the error the second time I print in the while loop in main() when counter = 1. What I don't understand is that if I comment out that printf statement and look at the value of temp value in my IDE (MVSE 2013) it is exactly as I wanted and expected i.e. temp will be 1 then 2,3,4,-1.
What is going on please and thanks in advance for any help.

Firstly, in case you're wondering how this appeared to sometimes work, you really should read this stellar answer to another somewhat related question.
In short, you're saving an address to an automatic variable from inside a function, then treating said-address like it is still valid after the function returns. That the automatic variable is a pointer referring to dynamic data is irrelevant. The variable itself is no longer valid once the function expires, and thus dereferencing its use-to-be-address invokes undefined behavior:
void changeAll(int ***a1PtrPtrPtr, int nToAdd)
{
// NOTE: local variable here
int *bPtr = (int *)malloc((arraySize(**a1PtrPtrPtr) + 1) * sizeof(int));
int i = 0;
while (*(**a1PtrPtrPtr + i) != -1){
bPtr[i] = *(**a1PtrPtrPtr + i);
i++;
}
bPtr[i] = nToAdd; i++;
bPtr[i] = -1;
// NOTE: saving address of local variable here
*a1PtrPtrPtr = &bPtr;
}
With how this is setup, the quickest fix is simply this:
**a1PtrPtrPtr = bPtr;
instead of what you have. This will save the dynamic allocation result to the correct location (which is ultimately the address held in aPtr back in main()). It looks hideous (and frankly, it is), but it will work.
Best of luck.

Related

Why is my array holding garbage values/segfaulting after passing it into another function?

I have a function that mallocs an array to hold value to encode into. After the values are encoded into the integer array, that array itself gets passed by reference (at least thats the theory). However, I was getting garbage values when I compiled the function so I started throwing print statements everywhere to see what was going on. Right after the second function gets called and the array is passed, the I realize that the print statements are segfaulting, which is strange to me.
Primary function:
void top_left_justify(char **pieces)
{
int i;
int j;
int count;
int *values; //array to be passed
i = 0;
if (!(values = (int *)malloc(sizeof(int) * 4)))
return ;
while (pieces[i] != 0)
{
j = 0;
count = 0;
while (pieces[i][j])
{
printf("count = %d\n", count);
if (pieces[i][j] == '#')
values[count++] = j;
j++;
}
printf("encoded indexes are: %d, %d, %d, %d\n", values[0],
values[1], values[2], values[3]); //test printout shows me it works here
top_left_helper(&values, pieces[i]); //PASS BY REFERENCE??
i++;
}
}
However, after it gets passed into this function:
void top_left_helper(int **values, char *pieces)
{
int i;
int j;
i = 0;
j = 0;
printf("value of values[0] = %d\n", *values[0]); //prints correct value
printf("value of values[0] = %d\n", *values[1]); //segfaults
left_helper(&*values);
top_helper(&*values);
while (i < 16)
pieces[i++] = '.';
while (j < 4)
pieces[*values[j++]] = '#';
}
It segfaults on the second print statement. I cannot really see an explanation for this other than my misunderstanding how passing parameters by reference and memory works. Please shed some light.
EDIT:
After some testing, it seems if I print out values by incrementing the pointer instead of array access, I am able to properly access the values to print. But that doesn't make any sense to me still why an array access wouldn't work. (following lines were added in second function)
printf("value of values[0] = %d\n", **values);
*values = *values + 1;
printf("value of values[1] = %d\n", **values);
*values = *values + 1;
printf("value of values[2] = %d\n", **values);
*values = *values + 1;
printf("value of values[3] = %d\n", **values);
This isn't doing what you think it is:
*values[1]
[] has higher precedence than *, so this first indexes values as an array, then dereferences the value it gets back. But what you passed into this function is a pointer to a variable which is also a pointer. So values[1] doesn't make sense. You get away with *values[0] because it's the same as **values What you want is:
(*values)[1]
However, unless you need to modify vaules itself, for example to use realloc on it, you don't need to pass its address. Just pass it as a int * as you do with pieces[i]:
void top_left_helper(int *values, char *pieces)
{
int i;
int j;
i = 0;
j = 0;
printf("value of values[0] = %d\n", values[0]);
printf("value of values[0] = %d\n", values[1]);
left_helper(values); // probably need to change left_helper the same way
top_helper(values); // and also top_helper
while (i < 16)
pieces[i++] = '.';
while (j < 4)
pieces[values[j++]] = '#';
}
Then change the call accordingly:
top_left_helper(values, pieces[i]);

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.

C - can variate location be promoted?

I am new to the language and was trying a simple code. I wanted to try to create a loop based on pointers. but it seems like you can not promote variate location like in assembler. or i just did it wrong? and if i really can't can i force a new variadate to be born in specific location? that was my code
#include <stdio.h>
int main(void) {
int firstnumber = 1;
int *beginning = &firstnumber;
printf("%i %i \n",firstnumber,beginning);
Test1(firstnumber,beginning);
return 0;
}
Test1 (int num, int begin)
{
int reserve = num;
if(num != 100)
{
&num +=2;
num = (reserve+1);
return Test1(num, begin);
}
else
{
int assist = begin;
while(*assist != 100)
{
printf("/n \n %i %i \n /n",num,assist);
&assist += 2;
}
}
}
I know it might look ridiculous but i'm really curious
You're thinking about this backwards. Pointers are the variables you can move around, so use them for anything you want to move around.
firstnumber is an integer variable - the compiler decides where it is stored and you can't tell the compiler to rebind the name firstnumber to a different location. You can, however, move a pointer around as much as you like. So,
void Test1(int num) {
&num +=2;
num = 42;
}
is nonsense, but
void Test2(int *num) {
num += 2;
*num = 42;
}
is fine - so long as num+2 is still a valid allocated object. For example, you could call it like
int i[5];
Test2(i); /* sets i[2] = 42 */
(if you pass in an array of fewer than 3 integers you get a runtime bug rather than a compile error, as Test2 damages your stack frame or other memory it shouldn't be touching).
No, you cannot promote/change variable location.
So this:
int num;
&num +=2;
does not make sense, and will result in an error:
error: lvalue required as left operand of assignment
&num +=2;
^~
Same for:
int assist;
&assist += 2;
Your code will compile only if you modify these statements (but now the logic is changed, you should work on that), but now it will result in an infinite loop, since your function never returns in the else case:
#include <stdio.h>
void Test1 (int num, int* begin);
int main(void) {
int firstnumber = 1;
int *beginning = &firstnumber;
printf("%i %i \n",firstnumber, *beginning);
Test1(firstnumber, beginning);
return 0;
}
void Test1 (int num, int* begin)
{
int reserve = num;
if(num != 100)
{
num +=2;
num = reserve + 1;
return Test1(num, begin);
}
else
{
int assist = *begin;
while(assist != 100)
{
printf("/n \n %i %i \n /n",num,assist);
assist += 2;
}
}
}
Good luck!
OK i checked the code deeper and got several conclusions:
function variable can not inherit his ancestor adress. therefore using a function for the task is useless unless i use some static variable
I had another conclusion but i don't remember what it was. sorry and thank you for your time

How can I store these numbers in C?

Lets say you had an array like this
{ 1 2 5 7 2 3 7 4 2 1 }
And you wanted to store that the difference between the first half of the array and the second half is at positions 2 and 4.
The trick is, I need to use those stored numbers later in other code, so what I can't figure out is how I would store these numbers.
I have this method
int * getPositions(int *array, int size){
int * c[(size/2)];
int counter = 0;
for(int i = 0; i < size /2; i++) {
if (*(array + i) != *(array + (size - 1) - i)) {
c[counter]= (int *) i;
counter++;
}
}return (int *) c;
}
but it seems to be storing -1774298560 into every location. I know that cause when I try to print it
int c = (int) getPositions(array, size_of_array);
for(int i = 0; i < ((size_of_array/2)); i++){
printf("%d\t", c);
}
all it prints out is
-1774298560 -1774298560 -1774298560 -1774298560 -1774298560
PS: I have array and size_of_array initialized somewhere else.
PS: I have taken the comments into consideration and changed the code to the following
int * getPositions(int *array, int size){
int * c = (int *) malloc((size_t) (size/2));
int counter = 0;
for(int i = 0; i < size /2; i++) {
if (*(array + i) != *(array + (size - 1) - i)) {
c[counter]= i;
counter++;
}
}
If the function should return a simple int array, you need to declare a pointer-to-int, and then call malloc to reserve space for the array. Then fill in the array, and return the pointer. The calling function will need to free the memory at some point.
int *getPositions(int *array, int size)
{
int *c = malloc( (size/2) * sizeof(int) );
if ( c == NULL )
return NULL;
// put stuff in the array using array syntax, e.g.
c[0] = array[0];
return c;
}
Call the function like this
int *c = getPositions( array, size );
if ( c != NULL )
for( int i = 0; i < (size/2)); i++ )
printf( "%d\t", c[i] );
free( c );
Notes:
Yes, error checking in C is a pain, but you must do it, or your
program will randomly crash.
You are allowed to use array syntax with a pointer, just be sure you don't read or write past the end of the memory that the pointer references.
It's legal to pass a NULL pointer to free.
Another option.
int * getPositions(int *array, int size);
int main() {
int array[] = { 1, 2, 5, 7, 2, 3, 7, 4, 2, 1 };
int size_of_array = sizeof(array) / sizeof(int);
int *ptr = getPositions(array, size_of_array);
for(int i = 0; ptr[i] != '\0' ; i++){
printf("%d\t", *(ptr + i));
}
return 0;
}
int * getPositions(int *array, int size) {
int temp[size/2];
int counter = 0;
for (int i = 0; i < size / 2 ; i++) {
if (array[i] != array[(size - 1) - i]) {
temp[counter++] = i;
}
}
int *c = malloc(counter * sizeof(int));
for (int i = 0; i < counter; i++) {
c[i] = temp[i];
}
return c;
}
My compiler going mad actually...which compiler you're using? Any modern static analyzer should have warned you
aftnix#dev:~⟫ gcc -std=c11 -Wall st.c
st.c: In function ‘getPositions’:
st.c:8:25: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
c[counter]= (int *) i;
^
st.c:11:6: warning: function returns address of local variable [-Wreturn-local-addr]
}return (int *) c;
^
st.c: In function ‘main’:
st.c:16:13: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
int c = (int) getPositions(array, 10);
So compiler is showing all the problems of the code. And your edited code doesn't even compile :
aftnix#dev:~⟫ gcc -std=c11 -Wall st.c
st.c:4:4: error: expected identifier or ‘(’ before ‘[’ token
int[] getPositions(int *array, int size){
^
st.c: In function ‘main’:
st.c:17:5: warning: implicit declaration of function ‘getPositions’ [-Wimplicit-function-declaration]
int c = (int) getPositions(array, 10);
Couple of things you have to take into consideration.
If you need to return a storage address, never try to return a local variable. As local variables are allocated in the Stack. Stack frames have the same lifetime of the function. Use malloc and co to allocate memory at the Heap. Understanding how the Runtime data structures are allocated and used is a very essential for a C programmer as C doesn't have fancy magical stuff under the hood. C is pretty much bare metal.
Stack Vs Heap
When passing arrays/pointers around, you should first think about your design first. Do you want to change your original array "in place"? or you want a different copy of "transformed" array. Usually you should try to avoid changing a memory "in place" as there might be other users to that. But if don't have such worries, you can then design your function as a "input->output" basis. That means you will not be returning void, and will return the transformed array itself.

Is this the right way to pass an array back from the function to main

The program is running without errors, but it stops after it runs this function since it seems that the array is not being passed back. Is this the right way to pass the array back to the function? I've included only the essential code below. Please could you point out where I might be wrong.
int matchedNumbersfunc(int lotoNumbers[],int ticketNumbers[], int *numbersRight);
int main()
{
int lotoNumbers[7];
int ticketNumbers[7];
int matchedNumbers[7];
int numbersRight = 0;
matchedNumbers[7] = matchedNumbersfunc(ticketNumbers, lotoNumbers, &numbersRight);
return 0;
}
int matchedNumbersfunc(int lotoNumbers[],int ticketNumbers[], int *numbersRight)
{
int matchedNumbers[7];
int i, k ,j;
*numbersRight = 0;
for(k=0;k<7;k++)
{
matchedNumbers[k] = 0;
}
for(i=0;i<7;i++)
{
for(j=0;j<7;j++)
{
if(ticketNumbers[i] == lotoNumbers[j])
{
matchedNumbers[i] = ticketNumbers[i];
}
}
if(matchedNumbers[i] != 0)
{
printf("You have a winning number: %d\n", matchedNumbers[i]);
*numbersRight = *numbersRight + 1;
if(matchedNumbers[6] != 0)
{
*numbersRight = *numbersRight - 1;
}
}
}
return matchedNumbers[7];
}
So, you are returning a single value rather than an array. And as it happens, you are returning a value off the end of the array, and assigning to a value off the end of another array. Your arrays have 7 elements, indexed 0 to 6.
What you need to do is pass an array to the function and let the function populate it. A simple example:
void foo(int array[], size_t count)
{
for (size_t i = 0; i < count; i++)
array[i] = i;
}
Which you would call like this:
int myArray[7];
foo(myArray, 7);
Another solution is to allocate a new array dynamically in your function and return a pointer to that array with this prototype:
int* matchedNumbersfunc(int lotoNumbers[],int ticketNumbers[], int *numbersRight);
Your revised function would start like this:
int* matchedNumbers;
int i, k ,j;
*numbersRight = 0;
matchedNumbers = (int*) calloc (7, sizeof(int));
if (matchedNumbers==NULL)
return NULL;
for(k=0;k<7;k++)
...
return (matchedNumbers);
In the main() you do not need to allocate the table, but just a pointer:
...
int *matchedNumbers;
...
matchedNumbers = matchedNumbersfunc(...);
if (matchedNumbers==NULL)
{ /* not enough memory - some kind of error processing */ }
free (matchedNumbers); // once you don't need the result anymore
return 0;
For your simple programme dynamic allocation could be overkill. But for more complex processing, this approach could be useful as well.

Resources