I have this code interaction with 2 files, but I am getting a segmentation error in these two functions and I need help figuring out why. fileA.c passes an int** to a function in fileB.c, the int** serves as an output parameter because I want to make an int array in fileB and have foo point to it so I can print it in fileA. In fileB.c, I make an array, and set the pointer to it.
size and foo are initialized in another function in a main file. It compiles fine, the output though would be (if size == 10) :
0 1 2 3 4 5 6 7 8 9
Segmentation fault
In fileA.c:
void testPointing(int size, int** foo) {
initialize(size, foo);
int i;
for(i = 0; i < size; i++) {
printf("%d ", (*foo)[i]);
}
}
fileB.c:
void initialize(int size, int** foo) {
int* a;
a = (int*)malloc(size * sizeof(int);
int i;
for(int i = 0; i < size; i++) {
printf("%d ", a[i]);
}
printf("\n\n");
foo = &a;
}
I need help fixing and understanding why I am getting a segmentation fault. Whenever I opt to put the loop located in fileA.c after
foo = &a
in fileB.c instead, it compiles and shows a correct output.
The address returned by malloc() is what holds your data, and that's stored in a, not &a. &a is just the address of the local variable a.
Also, foo is just the local function argument of initialize(), not the passed argument of the caller; that's *foo. That leaves the caller's foo unset, which is why you get a segmentation fault.
So instead of:
foo = &a;
you need:
*foo = a;
And the initial call to testPointing() should be something like this:
int* array;
testPointing(size, &array);
Related
I have a question. I wanna pass my own 2D array to pass function.And in that function,i will change my own array.So,there is a return.What i exactly know is that the code blow can be accepted by the compiler.But, i don't why it is.When i take the int (* aaa)[3]; out of the main function,it works well.But , when it is inside the main,there will throw an exception that unable to use the uninitialized aaa.I wonder why could this happan.
int* pass(int (*a)[3]) {
a=(int*)malloc(sizeof(int*)*2);
a[0][1] = 1;
a[0][2] = 2;
return a;
}
int (* aaa)[3];
int main() {
aaa = pass(aaa);
printf("%d", aaa[0][2]);
}
this could work.
int* pass(int (*a)[3]) {
a=(int*)malloc(sizeof(int*)*2);
a[0][1] = 1;
a[0][2] = 2;
return a;
}
int main() {
int (* aaa)[3];
aaa = pass(aaa);
printf("%d", aaa[0][2]);
}
but,this can't work.
When int (* aaa)[3]; appears outside of any function, it aaa is automatically initialized to a null pointer. When it appears inside a function, it is not initialized.
The code aaa = pass(aaa); passes aaa to the routine named pass. This is a use of the value of aaa. When aaa has been initialized, that is fine. But, when aaa is not initialized and you attempt to pass its value, the behavior is not defined by the C standard. This is what the compiler is warning you about.
Next, let’s examine this code:
int* pass(int (*a)[3]) {
a=(int*)malloc(sizeof(int*)*2);
a[0][1] = 1;
a[0][2] = 2;
return a;
}
This code never uses the value of a that is passed to it. When a function is called, its parameter, a in this case, is given a value (which comes from the argument the caller passed). This parameter is a separate variable from the argument. Assigning a a value with a=(int*)malloc(sizeof(int*)*2); does not change the value of aaa in the calling routine. So this code assigns a new value to a without using the old value.
Because of that, the routine does not need a parameter passed to it. It could be written to use a local variable instead, like this:
int (*pass(void))[3] {
int (*a)[3] = malloc(2 * sizeof *a);
a[0][1] = 1;
a[0][2] = 2;
return a;
}
The void in this means pass does not take any arguments.
Note that I changed malloc(sizeof(int*)*2 to malloc(2 * sizeof *a). sizeof(int*)*2 is wrong because it requests space for two pointers to int. But a points to arrays of three int, so, to get two of those, you need space for two arrays of three int. That is 2 * sizeof(int [3]). However, it is easier to write this as malloc(2 * sizeof *a), which means “two of whatever a points to”. This is also better because it reduces the frequency with which errors are made: Even if the declaration of a is changed, this sizeof *a will automatically adjust without needing to be edited. With sizeof(int [3]), any edit to the declaration of a would require another edit to the sizeof.
Also, I removed the (int*) to cast the result of malloc. In C, a void *, which is the type malloc returns, will automatically be converted to whatever object pointer type it is assigned to. There is no need for an explicit cast, and using an explicit cast can mask certain errors. (However, if you compile the program with a C++ compiler, it will complain about the lack of a cast, because the rules are different in C++.)
Since the function is returning a pointer to an array of three int, not an pointer to an int, I changed its declaration to int (*pass(void))[3].
With these changes, the program could be:
#include <stdio.h>
#include <stdlib.h>
int (*pass(void))[3]
{
int (*a)[3] = malloc(2 * sizeof *a);
a[0][1] = 1;
a[0][2] = 2;
return a;
}
int main(void)
{
int (*aaa)[3] = pass();
printf("%d\n", aaa[0][2]);
}
maybe this helps you a bit to see that C is 'flexible' when it comes to arrays.Because in the first part the assumed array declaration is given by datalen in malloc of the initAAA function and returns the pointer to the memory that is allocated. And still in the for loop we can access the data with index.
The second part of main declares just same data 'bbb' as the first 'aaa' but this time not as pointer and the initiation of the data fields with zeros (0) is done with the curly parenthesis. {}. A boring for loop thru all the indexes and set each data field with int 0 would just do it also. But who wants more code than needed.
#include <stdio.h>
#include <string.h>
int *initAAA(int *p, uint entrys) {
size_t datalen = entrys * sizeof *p;
p = malloc(datalen); // p is a pointer here.
// copy character '0' starting at address of p up to datalen addresses
// easier then writing a for loop to initiate safely.
memset(p, 0, datalen); // defined in string.h
return p;
}
int main(void) {
const uint maxAssets = 3;
const uint entrysPerAsset = 2;
int *aaa = NULL; // always a good idea, to set pointers to NULL before allocating memory for it. Because you can check if (aaa==NULL) initAAA(...
uint entrys = maxAssets * entrysPerAsset;
aaa = initAAA(aaa,entrys);
printf("address:%p items:%d \n",aaa, entrys);
for (uint i = 0; i < entrys; i++) {
printf("%d ", aaa[i]);
}
free(aaa); // malloc without free, bad idea!
printf("\n---\n");
int bbb[maxAssets][entrysPerAsset] = {0,0,0,0,0,0};
for (uint a = 0; a < maxAssets; a++) {
for (uint e = 0; e < entrysPerAsset; e++) {
printf("%d ", bbb[a][e]);
}
}
// bbb does not need free(bbb); because it is released with the function end.
// and yep, there was no malloc for bbb. so we are done.
}
and by the way. welcome to C.
Please explain (reason for the output) what happens as a result of running the two segments of code. Please explain their difference too. There are two versions of setArr(int, int) as explained below...
#include <stdio.h>
void setArr(int, int);
int *arr[10]; // array of 10 int pointers
int main(int argc, char *argv[]) {
int i;
setArr(0, 0);
setArr(1, 100);
setArr(2, 200);
setArr(3, 300);
setArr(4, 400);
for (i = 0; i < 5; i++)
printf("arr[%d]: %d\n", i, *arr[i]); /* should be 0,100, 200,300,400 */
return 0;
}
Versions of setArr
Version A
void setArr(int index, int v) {
int i = v;
*arr[index] = i;
}
Output: Segmentation fault (core dumped)
Version B
void setArr(int index, int v) {
int i = v;
arr[index] = &i;
}
Output:
arr[0]: 400
arr[1]: 32748
arr[2]: 32748
arr[3]: 32748
arr[4]: 32748
I presume the values from running Version B are just random values.
I am fairly new to pointers I have knowledge in Java, so please explain it as beginner friendly as you can :)
You are hitting a lot of undefined behavior scenarios, but I will explain what is likely happening.
arr is an array of 10 pointers to integers.
int * arr[10]; // array of 10 int pointers
And when declared as a global variable, all of those pointers are going to be zero-initialized - so hence, it's an array of 10 NULL pointers.
So this line in version A, is dereferencing the address at arr[index]:
* arr[index] = i;
Is effectively saying this:
*(NULL) = i;
And that will certainly crash consistently.
In Version B, you have it as:
int i = v;
arr[index] = &i;
So now you are correctly assigning a pointer to a slot in the array. However that address getting assigned is to a local stack variable, i, which goes out of scope as soon as the function returns. So when you print the value at that address, it's most certainly been clobbered from other calls writing on top of the stack. (Or technically this "undefined behavior" of accessing a memory address of a stack variable that has gone out of scope.)
Better:
void setArr (int index, int v){
arr[index] = malloc(sizeof(int));
*arr[index] = v;
}
The above allocates memory for the address that you want to copy that value into. You're on your own for how to free that memory.
Alternatively:
Just declare arr as an array of integers instead of pointers:
int arr[10];
void setArr (int index, int v){
arr[index] = v;
}
And then print normally without the * deference thing on arr.
printf("arr[%d]: %d\n", i, arr[i]);
Version A says "the contents of an undefined pointer equals i" - undefined behavior = crash. Basically you are trying to write to some unknown location in memory.
Version B says "Some pointer = some address" - still undefined behavior as &i goes out of scope, but it is still an address and so it "kind of works". Here you are writing to "good" memory locations, but reading from bad ones.
in first case, you have defined the "array of pointers" to integer. They are not integer pointers. Either you will have to allocate memory (preferably using melloc/calloc functions) before storing any value to them OR you can define the array of integer like this:
int (*a)[10]
The following link may show you some idea about it: Difference between *ptr[10] and (*ptr)[10]
In second case, you are saving the address of integer into integer pointer, which is ok, but int i is local variable to function setArr(). This will therefore, the value of int i will be dereferenced every time the function setArr() exits. Therefore you are getting undefined behavior for 2nd case. Either you can use static int i OR use global variable (not preferred) OR use pointer to integer assignment.
#include <stdio.h>
int main()
{
int i = 10;
int *p = &i;
foo(&p);
printf("%d ", *p);
printf("%d ", *p);
}
void foo(int **const p)
{
int j = 11;
*p = &j;
printf("%d ", **p);
}
What wii be the final output
Why Third printf will print undefined value ?
Within foo, you assign a value to *p which points to a location on the stack that's been allocated to foo. When foo returns, the stack is popped, and that location is free for reuse — but the p in main still points to it.
When you call printf in main the first time, it happens that that that location on the stack hasn't (yet) had any new data written to it, and so reading *p gives you 11, and you push that on the stack along with some other things for the call to printf, and it succeeds in printing 11. But the action of calling printf changes the data on the stack, including (potentially) the location that p (in main) points to, because the stack was popped after foo returned.
The second call then uses the data from that stack location again, which may have been changed by the first call to printf.
Moral of the story: Don't keep pointers to stack locations that have been popped.
the "i" in foo is stack-allocated, every thing will work fine until it goes off from the memory, so printf of foo will work fine,while the second printf and the third printf will work until the integer i of foo goes off from the memory. This is a system issue, it has the probability that the 2 last printf's work or don't work. If you wanna them work all the time you need to heap-allocate integer i of foo using mallo
Third printf is printing the right value. The problem is that j is an automatic local variable and it is no longer exist once function return. Therefore, p in main is not pointing to the place you are expecting and ultimately your program invokes undefined behaviour.
Possible solutions:
1. Use static keyword in the declaration of j
void foo(int **const p)
{
static int j = 11;
*p = &j;
printf("%d ", **p);
}
2. Dynamically allocate j
void foo(int **const p)
{
int *j = malloc(sizeof(int));
*j = 11;
*p = j;
printf("%d ", **p);
}
When void foo() is called ,new stack frame gets created on stack so int j = 11; being a local variable goes into this stack frame . So say int j is at address 0x000ffd with value 10 so your *p now stores this address . Now what happens when this function returns stack unwinds
During Stack Unwinding , it does all the work of cleanup. so all data which is into that stack frame gets destroyed so now that address 0x000ffd might have same value or something different but variable j is not associated to it now. So its undefined behavior
I have been learning arrays, but theres one thing that I cant figure out.
I borrowed two books for C and looked online, but found no solution.
My function timesTen multiplies every array elemenet that I have by 10,
then returns pointer of that array back function main()
How can I copy array a[2] directly in array x[2]?
I would usually use for loop, but I cant, because arguments are in two different functions.
Solution has probably got something to do with pointers, so feel free to post sollution here, but is there any way around them aswell?
Heres the source code:
#include <stdio.h>
int timesTen(int a[])
{
int i;
for (i=0;i<2;i++)
{
printf("%d\t", a[i]);
a[i]*=10;
printf("%d\n", a[i]);
}
return a;
}
int main()
{
int i;
int x[2];
int a[2]={10,50};
// i know here's an error, but how do I fix it? I cant put x[0]=timesTen(a[0])
x[2] = timesTen(a);
//also what if there is array a[10], and I want to copy it in x[5]
for (i=0;i<2;i++)
printf("%d\n", x[i]);
return 0;
}
Thanks!
What you need to understand is the distinction between arrays and pointers. When you declare your two arrays in main(), you allocate two times memory for two integers. That's fine. But in C, you simply cannot pass arrays around (as in: implicitly allocate a new slap of memory and copy the data of the source array into this memory region). Instead, any array identifier will decay to a pointer to the first element of the array in almost all situation. So when you write
int x[2];
int a[2]={10,50};
timesTen(a);
this code is precisely equivalent to
int x[2];
int a[2]={10,50};
timesTen(&a[0]);
So, why does that not clash with your declaration of timesTen()? Because array parameters in function declarations decay right there, on the spot, into a pointer! So, your function declaration is precisely equivalent to this one:
int timesTen(int* a) {
This is one of the least understood features of the C language, and admittedly, it is hard to wrap your brain around this, but once you understand what pointer decay means, you will be much more at ease using pointers and arrays.
So, back to your question. Since you passed only a pointer to your array to timesTen(), and since you modify this array, the changes are directly visible in main(). There are two ways to achieve the behavior you want:
You can change the definition of timesTen() to copy the data into a destination array:
void timesTen(int size, int* source, int* dest) {
for(int i = 0; i < size; i++) dest[i] = 10*source[i];
}
int main() {
int x[2];
int a[2]={10,50};
timesTen(2, a, x); //pointer decay!
//x now contains {100, 500}
}
You can copy the data into the destination array before calling your function to modify the destination array:
void timesTen(int size, int* data) {
for(int i = 0; i < size; i++) data[i] = 10*data[i];
}
int main() {
int x[2];
int a[2]={10,50};
memcpy(x, a, sizeof(a)); //the sizeof operator is one of only two places where no pointer decay happens!
timesTen(2, x); //pointer decay!
//x now contains {100, 500}
}
In the function timesTen, since a is an array, each modification made to it in the function is also done to the parameter you passed (call by address not by value). Therefore you don't need to returns anything.
void timesTen(int a[])
{
int i;
for (i=0;i<2;i++) a[i]*=10;
}
And you just call it by:
timesTen(a);
You probably want something like this:
timesTen(a);
memmove(x, a, 2 * sizeof(x[0]));
instead of
x[2] = timesTen(a);
Note that your function does not need to return anything, because it is modifying the array on its original place. In C if you have an array parameter, it means that only a pointer is passed, not the whole array.
in main function:
int *p;
int i;
p = timesTen(a);
for ( i = 0; i < 2; i++ )
{
printf( "%d\n",*(p + i)); // here you can print the values returned from your function
}
Through pointers you could have eaisly managed it
main ()
{
int a[ 2 ];
int *ptr = timesTen(a);
for ( int i=0; i<2 ; i++)
{
printf("%d",ptr[i]);
}
And as far as
x[2] = timesTen(a);
Is concerned note that x[2] will give "value at 2nd adress from adrees of base that is x"
And it is not a variable but it is a value and you cant assign to a value.
Technically x[2] is not a lvalue.
I have been using java for long time but for some reason I need to use C (ANSI C not C++) to write a simple code. I need to pass the pointer from outside to a function, allocate some memory to the pointer and assign some values also before the function return. I have my code like
#include <stdio.h>
#include <stdlib.h>
void test(int *a)
{
int n=3;
// I have to call another function t determine the size of the array
n = estimatesize(); // n >=3
// I tried fix size n=10 also
a = (int*)malloc(n*sizeof(int));
a[0] = 1;
a[1] = 2;
a[2] = 3;
}
void main(void)
{
int *s=NULL;
test(s);
printf("%d %d %d", s[0], s[1], s[2]);
}
I don't know why the code crashes. I thought at the beginning it is estimatesize() return wrong number but even I fix n to 10, the error still there. So I cannot pass a pointer to a function for memory allocation? If so, how can I dynamically create memory inside a function and pass it out? I know it may be a safe problem in this way but I just want to know if it is possible and how to do that. Thanks.
There are two solutions to this: Either return the pointer from the function, or pass the argument by reference.
For the first one, you simply don't take any arguments, instead you return the pointer:
int *test(void)
{
int *a = malloc(...);
...
return a;
}
int main(void)
{
int *s = test();
...
}
For the second one, you need to pass the address of the pointer, in other words a pointer to the pointer, using the address-of operator &:
void test(int **a)
{
*a = malloc(sizeof(int) * 3);
for (int i = 0; i < 3; ++i)
(*a)[i] = i;
}
int main(void)
{
int *s;
test(&s);
...
}
The reason it doesn't work now, is because the pointer (s in main) is passed by copying it. So the function test have a local copy, whose scope is only in the test function. Any changes to a in the test function will be lost once the function returns. And as s is copied for the argument, that means that s in main never actually changes value, it's still NULL after the function call.