the function corrupted my array in C - c

Hello I'm build a function are printing array with pointers
on c with Visual Studio 2015.
while i run the function this send me this massage:
Run-Time Check Failure #2 - Stack around the variable 'arr' was corrupted.
this the function:
void arrprint(int* arr, int size)//printing numbers:
{
size = (int)arr + size*sizeof(int);// the last adress of the array
int* firstAdress = arr;
for (arr=firstAdress; arr < size; arr++)
{
printf("%2d", *arr); //printing
}
*arr = firstAdress; //for not destroy the array
printf("\n");
}
thanks for helpers

This line
*arr = firstAdress; //for not destroy the array
destroys the array. You are writing into the memory when you dereference arr.
Since in C, everything is passed by value, you do not have to worry about corruption when you change arr in the function. So, you do not need firstAdress.
void arrprint(int* arr, int size)//printing numbers:
{
int* lastAddress = arr + size;
int* firstAdress = arr;
for (arr=firstAdress; arr < size; arr++)
{
printf("%2d", *arr); //printing
}
printf("\n");
}
After Updating, the code should look like this. You should notice that arr which is being changed here, is only being changed in this function, and the actual array pointer (in the caller function) is intact and safe.

You're trying to use size as an int *. Use an actual int * instead.
Also, by setting *arr = firstAddress, what you're really doing is writing the address of the array into the first element in the array. Also, since arr is a local variable, changes to it don't affect the variable in the calling function.
void arrprint(int* arr, int size)//printing numbers:
{
int *lastAddress = arr + size;
int *firstAdress = arr;
for (arr=firstAdress; arr < lastAddress; arr++)
{
printf("%2d", *arr); //printing
}
printf("\n");
}

Personally think the best solution is:
void arrprint(int* arr, int size)//printing numbers:
{
int *lastAddress = arr + size
int *firstAddress = arr;
for (firstAddress = arr; firstaddress < lastAddress; firstaddress++)
{
printf("%2d", *firstAddress); //printing
}
printf("\n");
}
Reason you do not alter the original pointer. You can also use const int* arr in the function declaration, then you will get a compiler error if you dereference the pointer.

Related

Value of an array does not change in call by address

In this program new value will be added to the array at end. When the memory is reallocated why it is not reflected back to the actual parameter
#include<stdio.h>
void insertion(int* arr,int *n)
{
int val,n1=*n;
int *temp;
printf("\nEnter element to append");
scanf("%d",&val);
temp=malloc(sizeof(int)*n1);
for(i=0;i<n1;i++)
{
temp[i]=arr[i];
}
n2=n1+1;
arr=malloc(sizeof(int)*n2);
for(i=0;i<n1;i++)
{
arr[i]=temp[i];
}
arr[n1]=val;
*n=n2;
}
int main()
{
int n=4;
int arr[4]={1,2,3,4},i;
insertion(arr,&n);
for(i=0;i<n;i++)
{
printf("\t%d",arr[i]);
}
}
There are two reasons for this.
First, you're assigning the return value of malloc to arr, which is a parameter to the function and therefore local. This means that changing the value of arr isn't reflected in the calling function.
Even if you fixed this, you would have a problem because arr in main is an actual array allocated locally, so you can't change its size.
You would first need to change arr in main to be a pointer and to allocate space for it with malloc so that you can use realloc later, and you need to change insertion to take a int ** so that the actual pointer value in main can be changed.
Because the parameter is passed by value.
You change arr in insertion, there's no reason that should change arr in main. They're different variables. This is how C works.
But in main arr is an array, which means it couldn't be changed even if you got the code right.
Here's how to do it right, if you want to change something in main you have to return the vaue from your function.
#include<stdio.h>
int* insertion(int* arr,int *n)
{
...
return arr; // return the new value of arr
}
int main()
{
int n=4;
int* arr = malloc(n*sizeof(int)); // arr is a pointer, not an array
for (int i = 0; i < n; ++i)
arr[i] = i+1;
arr=insertion(arr,&n); // get the returned value from insertion
for(i=0;i<n;i++)
{
printf("\t%d",arr[i]);
}
}

Changing array inside function in C

I am learning C and confused why a array created in the main wont change inside the function, i am assuming the array passed is a pointer, and changing the pointer should've change the array , right ? can someone explain what is happening in this case?
thx for the help.
int main(){
int i, length = 10;
int array[length];
for (i = 0 ; i < length ; i++)
array[i] = i * 10;
printf("Before:");
print(array, length);
change(array, length);
printf("After:");
print(array, length);
return 0;
}
// Print on console the array of int
void print(int *array,int length)
{
int i;
for(i = 0 ; i < length ; i++)
printf("%d ", array[i]);
printf("\n");
}
// Change the pointer of the array
void change(int *array,int length)
{
int *new = (int *) malloc(length * sizeof(int));
int i;
for(i = 0 ; i < length ; i++)
new[i] = 1;
array = new;
}
I expected to see the following output:
Before:0 10 20 30 40 50 60 70 80 90
After:1 1 1 1 1 1 1 1 1 1
What i get:
Before:0 10 20 30 40 50 60 70 80 90
After:0 10 20 30 40 50 60 70 80 90
In c you can't pass a variable by reference, the array variable that you assign inside the function contains initially the same address as the passed pointer, but it's a copy of it so modifying it will not alter the passed pointer.
You need to pass the address of the pointer in order to be able to alter it, like this
// Change the pointer of the array
void change(int **array, int length)
{
*array = malloc(length * sizeof(int));
if (*array == NULL)
return;
for (int i = 0 ; i < length ; i++)
(*array)[i] = 1;
}
Then in main() you cannot assign to an array, doing so through this kind of function is surely undefined behavior. The array defined in main() is allocated on the stack and you cannot assign anything to an array since they are non-writeable lvalues so you cannot make it point to a heap memory location obtained with malloc(), you need to pass a pointer like this
int *array;
change(&array, length);
free(array);
If you want the function to replace the previous array, it will have to free() the malloc()ed data (note that passing NULL to free() is well defined), so
// Change the pointer of the array
void change(int **array, int length)
{
free(*array);
*array = malloc(length * sizeof(int));
if (*array == NULL)
return;
for (int i = 0 ; i < length ; i++)
(*array)[i] = 1;
}
then in main()
int *array;
array = NULL;
change(&array, length);
change(&array, length);
change(&array, length);
change(&array, length);
free(array);
will do what you apparently want.
Ok, i will make the answer short.
Arrays are always passed by reference in C
change(array, length);
In this line, it means reference to the first element of the array variable is passed to the function.
Now the function needs a pointer to catch the reference, it can be a pointer or it can be an array. Note that the pointer or the array is local to the function.
You received it in a pointer named array. Which is definitely a pointer but it is not the same as array in main function. It is local to the change function.
You declared a new array dynamically, and assigned a pointer named new with it. And all the changes you did were to new pointer.
Everything is ok till now.
Now you assigned the new pointer to the array pointer which is local to the change function.
This is the real issue. As even though the array is in heap section, and it will remain in the memory, but the *array and *new are local pointer variables.
Also array pointer in change function is different from array pointer in main function.
The solution to this problem is
Manipulate the data of array pointer directly.
void change(int *array,int length)
{
int i;
for(i = 0 ; i < length ; i++)
array[i] = 1;
}
In this way you are directly overwriting values of array in main function. Everything else is correct.
Summerization:
array pointer in change function is local to change function.
array in main function is local to main function.
Making change function's local array pointer point to array in heap section won't change data in actual array. You changed pointer's position, Not the array's data.
Your array in main is an array. It will decay to a pointer, to produce the behavior you expect, but it is not a pointer.
int a[10];
int* p = a; // equivalent to &a[0]; create a pointer to the first element
a = p; // illegal, a is NOT a pointer.
What your code is doing is copying the address of a into a function-local variable. Modifying it will have no more difference outside than changing length.
void change(int* local_ptr, size_t length)
{
local_ptr = 0;
length = 0;
}
int main()
{
int a[10];
int length = 10;
printf("before a=%p, length=%d\n", a, length);
change(a, length); // we copied 'a' into 'local_ptr'.
printf("after a=%p, length=%d\n", a, length);
}
If you wish to modify a pointer from the caller, you will need to use pointer-to-pointer syntax:
void change(int** ptr, size_t length)
{
// change the first element:
**ptr = 0;
// change the pointer:
*ptr = 0;
// but ptr itself is a function-local variable
ptr = 0; // local effect
}
However: There is a problem with what you are trying to do that goes deeper than this.
In your code, "int a" is an array on the stack, not an allocated pointer; you cannot free it and you should avoid mixing heap/stack pointers this way because eventually you'll free the wrong thing.
A simple example:
#include <stdio.h>
void print_array(const int arr[], const int n){
int i;
for(i=0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
}
void change_array(int arr[]){
arr[0] = 239;
arr[1] = 234234;
}
int main(){
int arr[10] = {};
print_array(arr,10);
change_array(arr);
print_array(arr,10);
return 0;
}
The output:
0 0 0 0 0 0 0 0 0 0
239 234234 0 0 0 0 0 0 0 0
If you are looking for the simplest way to modify the data pointed to by 'array', rewrite the 'change' function to:
// [OLD COMMENT] Change the pointer of the array
// [NEW COMMENT] Change the value(s) of data pointed to by 'array'
void change(int *array, int length)
{
int i;
for(i = 0 ; i < length ; i++)
array[i] = 1;
}
When you pass the name of the integer array called 'array', you are passing a pointer to the array data declared in main. In the function 'change' the pointer is copied (passed by value) and it is used in the function as it would have in main. No need for malloc.
You pass a pointer to the array array to the function change. In this function you create another array called new (using new as a name is a bad idea) and then assign it to the locally created function parameter array. You do not modify pointer in your main function. If you would like to do so, you should use
array = change(array,length);
in your main function and
int *change(int *array, int length) {
int *variable_called_new =(int *)malloc(length*sizeof(int));
[...]
return variable_called_new
}
in your change function.
To use pass by value:
Make the following change:
In function change(...), replace:
int i;for(i=0;i<length;i++)new[i] = 1;
To:
int i;for(i=0;i<length;i++)array[i] = 1;
^^^^^
EDIT:
But to use pass by reference:
//To change the contents of a variable via a function call
//the address of that variable has to be passed. So, if you
//want to change the contents of an array of int, i.e. int *array, you
//need to pass its address, not the variable itself, using the
//address of operator, it would look like this &array (read _the address of
// pointer to int "array")
//This requires you to change the prototype of your function:
void change2(int **a, int len)
{
int i;
for(i=0;i<len;i++) (*a)[i] = 1;//parenthesis bind * to a to assure
//array of pointers to int ( *[] )is populated
//
}
Then in main, make the following changes, and it will work as you purposed:
int main(){
int i,length=10;
int *array;
array = calloc(length, sizeof(int));
if(!array) return 0;
//or malloc if preferred. But note, in C,
//casting the output is not required on either.
//array = malloc(length*sizeof(int));
//if(!array) return 0;
for(i=0;i<length;i++)array[i]=i*10;
printf("Before:");print(array,length);
change2(&array,length);
printf("After:");print(array,length);
free(array);
return 0;
}
so when you pass the array you get the address of it's beginning:
memory address
|-junk-| 1000
|---0---| 1008 <- start of your array
|---10--| 1012
. .
. .
when you get the pointer in your function its value is 1008(example) so changing that will only mean you now point to another place. that is not what you want.
you can change the integers pointed at directly via the * operator, so
*array = 99; will change the first element,
*(array+1) = 98; the second and so on.
you can also, more naturally use the [] operator.
so in your function
array[0] = 99; will actually change the original array.
#include<stdio.h>
#include<stdlib.h>
// Print on console the array of int
void print(int *array,int length)
{
int i;
for(i = 0 ; i < length ; i++)
printf("%d ", array[i]);
printf("\n");
}
// Change the pointer of the array
void change(int **array,int length)
{
int i;
int *ar;
ar = (int *)malloc(sizeof(int *) * length);
for(i = 0 ; i < length ; i++)
ar[i] = 1;
(*array) = ar;
}
int main(){
int i, length = 10;
int *array;
array = (int *)malloc(sizeof(int *) * length);
for (i = 0 ; i < length ; i++)
array[i] = i * 10;
printf("Before:");
print(array, length);
change(&array, length);
printf("After:");
print(array, length);
return 0;
}
You are passing your array's reference to the function change() and the rererence is getting copied to pointer array in change.
And then you're creating a variable new and assigning the memory space using malloc and following that you're assigning some values to it.
Until now your pointer array in change() is pointing to the array in main.
In the next statement you're making your array in change() point to the space pointed by the variable `new and the pointar array is not pointing to the array in the main any more.
So instead of using new[i] = 1 use array[i] = 1 in change().

returning 2D array having error, need concept

I tried different methods but eventually got errors. Please give a solution and a brief explanation of the concept.
uint8_t **subBytes()
{
int i,j;
uint8_t r,c;
uint8_t t[4][4];
for(i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
r = pt[p1][j] & 0xf0;
r = r >> 4;
c = pt[p1][j] & 0x0f;
t[i][j] = (uint8_t *) malloc(sizeof(uint8_t));
t[i][j] = sBox[r][c];
}
p1++;
}
return t;
}
int main()
{
uint8_t **temp;
temp = subBytes();
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
printf("%x ", temp[i][j]);
}
printf("\n");
}
}
This is my original code. Here, I used malloc, but then too it is not working.
the memory space alloced for your matrix is a LOCAL VARIABLE.
The scope of a LOCAL VARIABLE is only within that function.
When you returned it is discarded.
In your code it is uint8_t t[4][4].
t is discarded right after return t.
So you return nothing and may cause undefined behavior.
You should use malloc to alloc memory for your matrix not just declare it locally.
in code
uint8_t **t.
t = malloc(sizeof(uint8_t) * 16 ) //size of a 4x4 matrix
then use t as a two dimension array and return t.like
t[0][0] = 1;
don't forgot to free it after use it out side of the function.
free(t);
m is LOCAL VARIABLES. When add returns, m is DESTROYED!
You SHOULD NOT return the pointer or reference of local variables. Look the following code:
int foo() { return 1; }
int *bar() { int i = 1; return &i; }
When I call foo(), it returns 1.
When I call bar(), it try to return the local variables, i's address. But when bar() returns, the i variable is DESTROYED! So the return pointer become trash pointer. (Sorry, I don't know how to say that term in English;)
You should use like that:
void bar(int *ret) { *ret = 1; }
int i;
bar(&i); /* now i is 1 */
or
int *bar()
{
int *p = (int *)malloc(sizeof(int));
*p = 1;
return p;
}
int *pi = bar();
/* now *pi is 1 */
...
free(pi); /* You MUST free pi. If not, memory lack is coming~ */
(I recommend first one. the second one require free and it can be mistaken.)
When a variable is declared (statically allocated) within a function, it is placed on what is called the stack, which is only local to that function. When the program leaves that function's scope, the variable is no longer guaranteed to be preserved, and so the pointer you return to it is essentially useless.
You have three options to fix your error:
Don't do it
Simply declare the array in the same function as you use it, don't bother with trying to return a pointer from another function.
Pass a pointer to a variable local to main
A pointer to a variable local to main will be valid until main returns, so you could do this:
void subBytes(uint8_t t[4][4]){
//perform initialization of matrix on passed variable
}
int main(){
uint8_t temp[4][4];
subBytes(&temp);
//...
}
Dynamic Allocation
This will probably give you more errors than it will solve in this case, but if you are heartset on returning a pointer to a matrix, you could malloc() the memory for the array and then return it, but you would have to free() it afterwards.
In C, there are several ways to dynamically allocate a 2D array. The first is to create it as a single array, and operate on the indices to treat it as 2D.
//...
int *arr = (int *)malloc(rows*cols*sizeof(int));
for (int i = 0; i<rows; i++){
for (int j = 0; j<height; j++){
arr[i*height + j] = i*j; //whatever
}
}
return arr; // type is int *
//...
Note that in this method, you cannot use array[i][j] syntax, because the compiler doesn't know the width and height.
The second way is to treat it as an array of arrays, so store an array of pointers to other arrays.
//...
int **arr = (int **)malloc(rows*sizeof(int *));
for (int i = 0; i<rows; i++){
arr[i] = (int *)malloc(cols*sizeof(int));
}
arr[i][j] = 86; //whatever
return arr; //type is int **
//...
For further information, see: Pointer to Local Variable

Function with return type array in C

I have the following function in C:
int[] function(int a){
int * var = (int*)malloc(sizeof(int)*tags);
....
}
*var is it a pointer to an array var?
If yes, how can I return the array (var) in the function?
You can't really return an array from a function, but a pointer:
int * function(int a){
int * var = malloc(sizeof(int)*tags);
//....
return var;
}
This code below could clarify a bit how array and pointers works.
The function will allocate memory for "tags" int variables, then it will initialize each element with a number and return the memory segment that points to the array.
From the main function we will cycle and print the array element, then we will free the no longer needed memory.
#include <stdio.h>
#include <stdlib.h>
int *function(unsigned int tags) {
int i;
int *var = malloc(sizeof(int)*tags);
for (i=0; i < tags; i++) {
var[i] = i;
}
return var;
}
int main() {
int *x;
int i;
x = function(10);
for (i=0; i < 10; i++) {
printf("TEST: %i\n", x[i]);
}
free(x); x=NULL;
return 0;
}
How about:
int* function(int tags){
int * var = malloc(sizeof(int)*tags);
//....
return var;
}
Arrays and pointers to the base element type are (mostly) synonymous in C/C++, so you can return a pointer to the first element of an array and use that as if it was the array itself.
Note, your code has an input parameter a, but using tags to allocate the memory for the array. I assumed in the above code that you wanted to use the input parameter for that purpose
Also, you will have to call free() on the pointer returned by function above, when you are no longer using the array, to avoid memory leaks. malloc above allocates memory enough to hold tags number of ints, so the array is equivalent to int var[tags];
UPDATE: removed cast for malloc's return
In C, functions cannot return array types. For your purposes, you want to return a pointer to int:
int *function(int a)
{
int *var = malloc(sizeof *var * tags); // where is tags defined?
// are you sure you don't mean a here?
...
return var;
}
This will allocate a block of memory large enough to hold tags integer values and assign the address of the first element of that block to var. Note that var is a pointer to int, not a pointer to an array of int. That pointer is what gets returned from the function.
You can use the subscript oprerator on a pointer expression as though it were an array, like so:
int a = ...;
int *arr = function(a);
...
arr[0] = 0;
arr[1] = 1;
...
arr is a pointer expression, not an array expression, so sizeof arr will return the size of the pointer type, not the size of the block of memory that it points to (because of this, you will want to keep track of the number of elements you allocated separately).
In C an array is basically the same type as a pointer to an element of the array.
So char[] is basically char*
Don't forget to keep track of the size of the array, also I noticed that tags seems to be a global variable, most of the time it's a good idea to avoid global variables
Here is some example code:
#include <stdio.h>
#include <stdlib.h>
int* foo(size_t arrSize){
int* arr = (int*) malloc(sizeof(int)*arrSize);
return arr;
}
int main (int argc, char** argv){
printf("Printing array:\n");
int* arr = foo(42);
for(int i=0; i <42; i++){
arr[i]=i;
}
for (int i=0; i < 42; i++){
printf("Element: %d: %d\n", i, arr[i]);
}
free(arr);
return 0;
}

Convert list to array

I have functon that convert list in array:
void* list_to_array(SList* list)
{
int i;
int array_size = list_get_length(list);
void* array[array_size];
for (i = 0; i < array_size; i++)
{
array[i] = list_get_n_data(list,i);
}
return *array;
}
But when i try to test it:
int* a = (int*)list_to_array(list);
printf("%d" (int)a);
it's ok. I see first element. But when i try to get second or third element:
int* a = (int*)list_to_array(list);
a++;
printf("%d" (int)a);
I see first element + 4. if i try get third element i see first element value + 8 and etc... Why? What's wrong?
Thank you
You are returning a pointer to a stack memory location. That memory region is no longer valid once the function returns.
Also, instead of actually returning a pointer to the array, you are returning the first element in the array. The following code will return 1, not a pointer the array.
int array[] {1, 2, 3, 4};
return *array
You probably only need to make minimal changes your code to get it to work.
void** array = (void **) malloc(sizeof(void *) * array_size);
...
return array;
Just make sure that you release the memory that memory used for array when you are finished with it.
void **array = list_to_array(list);
// Use array
...
// Finished with array
free(array);
When you increase the pointer int* a by 1, it would actually increase it by sizeof(int), which is - on most systems, at least - 4.
So if
int* a = 0x40b8c438
then
a + 1
= ((void*) a) + sizeof(int)
= 0x40b8c43c
and
a + 2
= ((void*) a) + sizeof(int) * 2
= 0x40b8c440
You have three problems here. The first is trivial, you're returning the first element of the array with return *array, when what you mean is to return a pointer to the first element of the array with return array. DON'T STOP HERE! The second is that you are incrementing your pointer by 1, rather than by the size of the data you're pointing to. This will cause you to get wrong results. The third problem is much more serious:
You allocate memory for your array on this line:
void* array[array_size];
This memory is allocated on the stack, and this memory is no longer allocated when you return from the function. When you later reference this memory with the line:
int* a = (int*)list_to_array(list);
a is pointing to a region on the stack which is no longer in use. You get somewhat reasonable results with the code you have, but if you modify the stack after returning from your function, a will be pointing at the new memory. For example, if you use the following code:
int* a = (int*)list_to_array(list1);
int* b = (int*)list_to_array(list2);
printf("%d" (int)a);
You will (likely) see the first element of b. This is not guaranteed - You may also get a segmentation fault. Other code between the assignment to a and its use will also overwrite the contents of the memory you access in your printf statement.
You need to allocate your memory with the same scope as a.
// Prototype
void* list_to_array(SList* list, void* dest_array);
// C99 (Or use malloc)
void* array[list_get_length(list)];
int* a = (int*)list_to_array(list, array);
other_functions();
// Works every time!
printf("%d" (int)a);
The less serious problem is the fact that you're not incrementing your pointer by the correct amount. You need to use the sizeof() operator. Alternatively, you can access your array elements with [].
int* a = (int*)list_to_array(list, array);
printf("%d" a[1]); //Prints second element of a
a += sizeof(int) * 2;
printf("%d" (int)a); //Prints third element of a
You need to be careful with pointers, declare it this way:
int main()
{
int *array;
int i;
i = size(list);
array = list_to_array(list, i);
...
free(array);
}
int size(t_list *list)
{
int i;
i = 0;
while (list)
{
i++;
list = list->next;
}
return (i);
}
int *list_to_array(t_list *list, int size)
{
int *array;
int i;
t_list *temp;
i = 0;
if (list == NULL)
return (NULL);
array = (int*)malloc(sizeof(int) * size + 1);
temp = list;
while (temp)
{
array[i] = temp->data;
temp = temp->next;
i++;
}
return (array);
}

Resources