Okay I go through 2 layers of functions fun1 calls func2 calls func3 . I pass a pointer all the way down using basically int *ptr, at the lowest "level" of the call stack I also have another function that dynamically allocates memory for an int array. At the top level (func1 level) I always get null back for the passed pointer. I have traced down to func3 and the allocated memory is being filled with values, but as the call stack unwinds func3 -> func2 suddenly the pointer just goes away (0x0000_0000)? I don't understand at func3 level I basically say ptr = allocate_ptr_array, but from that return it goes to NULL! Even though I didn't free the memory, what in the world is going on? I know my question is confusing. I have watched this happen in the debugger though
The pointer is basically passed by value. You need to pass pointer to pointer (int **p) to get the memory allocated back in outer function.
function1(int *p)
{
p = //allocate memory using malloc
}
function2(int **p)
{
*p = //allocate memory using malloc
}
function3()
{
int *p;
function1(p);
// in this case pointer is passed by value.
//The memory allocated will not be available in p after the function call function1.
int **p;
function2(&p);
//in this case pointer to pointer p has been passed.
// P will have the memory allocated even after
//the function call function1
}
}
To illuminate aJ's (completely correct) answer with some code:
void func1(void)
{
int *int_array;
func2(&int_array);
/* Some stuff using int_array[0] etc */
/* ... */
free(int_array);
}
void func2(int **a)
{
/* ... stuff ... */
func3(a);
/* .... stuff ... */
}
void func3(int **a)
{
(*a) = malloc(N * sizeof **a);
}
Here is a good example for future reference bye other people. It makes sense after implementation and thanks to these guys.
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
void func3(int **ptr)
{
int i;
(*ptr) = (int *)malloc(25*sizeof(int));
for (i=0; i < 25; i++) (**ptr) = i;
printf("func3: %d\n",ptr);
}
void func2(int **ptr)
{
func3(ptr);
printf("func2: %d\n", ptr);
}
void func1(void)
{
int *ptr;
printf("ptr before: %d\n", ptr);
func2(&ptr);
printf("ptr after: %d\n", ptr);
}
void func4(int **ptr)
{
static int stuff[25];
printf("stuff: %d\n",stuff);
*ptr = stuff;
}
int main(void)
{
int *painter;
func1();
func4(&painter);
printf("painter: %d\n", painter);
return 0;
}
Related
My coding assignments came with it's header file, meaning we need to use the same data types, and not vary anything.
There is a lot of pointers, (mainly a lot of void *). Meaning things are confusing, more than difficult.
we have to do a separate function, just to increment the value referenced by a pointer. But given the nature of program, I don't want to constantly make new pointers.
The code is as follows:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void* intal_create(const char* );
void* intal_increment(void* );
void *intal_create(const char* str)
{
int a;
a=atoi(str);
return &a;
}
void *intal_increment(void *intal)
{
int *a= (int *)intal;//new pointer;
++*a;
//value referenced has been incremented;
*(int *)intal=*a;
return intal;
}
int main()
{
int * x;// void * return a pointer, need a pointert to int to pick it up
char *dummy;
gets(dummy);
x=(int *)intal_create(dummy);
printf("integer return is %d\n",*(int *)x);
printf("address stored is %p\n",(int *)x);
x=(int *)intal_increment(x);
printf("integer return is %d\n",*(int *)x);
printf("address stored is %p\n",(int *)x);
}
I wanted x to be the parameter called, and also for it to store the return value. The printf address is merely for my understanding.
The segmentation faults never end, and from my understanding, I'm just returning a pointer and asking a pointer to stop the return pointer
By incorporating all the comments. Mainly allocating memory to dummy before passing it gets() function and allocating memory in heap for the return pointer of intal_create.These two fixes solve the issue. Have a look at the following code for reference.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void* intal_create(const char* );
void* intal_increment(void* );
void *intal_create(const char* str)
{
int *a = (int *)malloc(sizeof(int));
*a = atoi(str);
return a;
}
void *intal_increment(void *intal)
{
//Here i am not allocating
int *a = (int *)intal;//new pointer;
(*a)++;
return intal;
}
int main()
{
int * x;// void * return a pointer, need a pointert to int to pick it up
char dummy[20] = {0};
fgets(dummy,5,stdin);
x = (int *)intal_create(dummy);
printf("integer return is %d\n",*x);
printf("address stored is %p\n",(void*)x);
x=(int *)intal_increment(x);
printf("integer return is %d\n",*x);
printf("address stored is %p\n",(void *)x);
//Make sure you deallocate the memory allocated in the intal_create function.
free(x);
}
I'm newbie in C language. If I assign the address of local variable to global pointer, What happens? Like,
#include <stdio.h>
void func();
int *ptr;
int main()
{
func();
}
void func()
{
int i = 0;
ptr = &i;
}
Is it correct way to assign the address of local variable to global pointer?
It just does what you do, there is nothing wrong about it, except that it probably is not what you want.
So it just assigns the address of i to ptr at the point you assign it. When you leave func this pointer gets invalid.
Note This behaviour is fully defined: The address of i at the place you assign it to the global variable is defined, and so you can assign it. The problem only comes into play later, when you try to dereference the variable after you left the function func. As long as you only use the global variable in func there is no problem in this (except that a global variable is really meaningless).
At this point, this variable doesn't exist anymore. And it is very likely that you either get a segfault or at least you get some strange numbers (because you have overwritten the old stack frame with some other values) in this case.
Just as a side note: What I mean with this stack frame thing. You can try this code on most compilers (without optimizations!)
#include <stdio.h>
int *ptr;
void f1() {
int i = 0;
ptr = &i;
}
void f2() {
int i = 1;
}
int main() {
f1();
printf("%d\n", *ptr);
f2();
printf("%d\n", *ptr);
}
Without optimizations, this will most probably print
0
1
Because the variable i will have the same address when calling f1 and f2 from main().
With optimizations, the call to f2() will be optimized.
Still: This is undefined behavior and must not be done.
Your syntax is correct, but the local variable ceases to exist because it belongs within the scope of the function call's code block. To resolve this, one option is to make the local variable static:
#include <stdio.h>
void func();
int *ptr;
int main()
{
func();
}
void func()
{
static int i = 0;
ptr = &i;
}
Another option would be to allocate new memory within the function call, setting the global pointer to the address of that newly allocated memory:
#include <stdio.h>
void func();
int *ptr = NULL;
int main()
{
func();
}
void func()
{
if(ptr != NULL)
free(ptr);
int *i = (int *)malloc(sizeof(int));
ptr = i;
}
What you've got is syntactically correct, and the code as written is semantically valid (but since ptr is never used, it is a bit pointless).
If you access ptr when it contains a pointer that has gone out of scope, you get undefined behaviour.
However, consider a slightly larger code fragment. Here, the code that sets ptr calls a function that uses ptr, and the variable that ptr points to is still defined, so there is no problem using the pointer.
#include <stdio.h>
void func(void);
void use_pointer(void);
int *ptr;
int main(void)
{
func(); // NB: argument not allowed with prototype!
int i = 20;
printf("%s: A %d\n", __func__, i);
ptr = &i;
use_pointer();
printf("%s: B %d\n", __func__, i);
}
void func(void)
{
int i = 0;
printf("%s: A %d\n", __func__, i);
ptr = &i;
use_pointer();
printf("%s: B %d\n", __func__, i);
}
void use_pointer(void)
{
printf("ptr = %p; *ptr = %d\n", (void *)ptr, *ptr);
*ptr = 42;
}
This is legitimate code — though using global variables is something you should generally avoid and perfectly well could avoid.
Sample output:
func: A 0
ptr = 0x7fff55be74ac; *ptr = 0
func: B 42
main: A 20
ptr = 0x7fff55be74cc; *ptr = 20
main: B 42
#include "stdafx.h"
#include "stdlib.h"
#include "string.h"
typedef struct
{
int a ;
char b;
char c[50];
}TEST;
void *allocate(int count,int size);
void FREE(TEST *ptr);
int _tmain(int argc, _TCHAR* argv[])
{
TEST *test = NULL ;
void *ptr = NULL ;
ptr = allocate(2,sizeof(TEST));
test = (TEST *)ptr;
test->a = 1;
test->b = 'A';
strcpy(test->c,"siva");
FREE(test);
if(test != NULL) //here Im getting issues, test remains pointing address
printf("\n Failed to free");
else
printf("\n Free Success");
return 0;
}
void *allocate(int count,int size)
{
void *ptr;
ptr = calloc(count,size); // here allocated successfully
return ptr;
}
void FREE(TEST *ptr)
{
free(ptr);
ptr = NULL ; // Deallocated Successfully
}
In this code, i just called one allocation function to allocate memory dynamically, after that i called FREE function to free that memory, both functions working properly only. but inside main function after called the free function, why still test pointer pointing to the memory?
It's because the variable ptr inside the FREE function is a local variable, changing it will only change the local variable, nothing outside of the function will be modified.
What you need to do is to pass the variable by reference, which is not supported by C. C only have passing by value. But reference argument-passing can be emulated using pointers. So you need to pass a pointer to the pointer:
void FREE(TEST **ptr);
Call this using the address-of operator &:
FREE(&test);
and inside the function use the dereference operator * to access the original pointer variable.
I have the following questions regarding pthread of posix.
When we receive data in pthread_join() returned by the function being executed by a thread, we type cast the variable like (void **) even though the variable is a single pointer.
int *x;
pthread_join(tid,(void**)&x);
printf("%d",*x);
Should I derefrence the type casted argument (in case of structure)? Why can't I do like
struct Data *obj= & (struct Data*)arg;?
int main()
{
...
pthread_create(tid,NULL,Foo,&obj);
...
}
void *Foo(void *arg)
{
struct Data *obj=* (struct Data*)arg;
}
How does pthread_join() internally receives the returned variable.
Regards
First of, you should never do (void**)&x as pointers off different types need not be of the same size.
Now, some scenarios (some valid, some working but invalid and some just broken):
Foo() returning a pointer to an int (valid):
void* Foo(void *arg)
{
int *ret = malloc(sizeof(int));
*ret = 42;
return ret;
}
void *ptr;
int *x;
pthread_join(thread, &ptr);
x = ptr;
printf("%d", *x);
free(x);
Foo() returning an int (invalid but usually work):
Platforms where int is larger than a pointer this will not work.
void* Foo(void *arg)
{
return 42;
}
void *ptr;
int x;
pthread_join(thread, &ptr);
printf("%d", (int)ptr);
Foo() returning a pointer to static int (invalid and never works):
All static memory in Foo() is freed when Foo() returns, before pthread_join() can copy the value.
void* Foo(void *arg)
{
int ret = 42;
return &ret;
}
void *ptr;
int *x;
pthread_join(thread, &ptr);
x = ptr;
printf("%d", *x);
You shouldn't do that: at your level of understanding of C casts should be simply forbidden.
If you learned that in a course, this is not really high quality.
First of all, &x is the address of a pointer so the result is int**, so well two indirections.
But casting that int away is dangerous, pointers to int and void don't have necessarily the same width on different platforms. So please do
void*x;
pthread_join(tid, &x);
printf("%d",*(int*)x);
The code confused me.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void create_int(int *p)
{
p = (int *) malloc(sizeof(int));
}
int main()
{
int *p = NULL;
create_int(p);
assert(p != NULL); /* failed. why? I've allocated memory for it. */
return 0;
}
You are not passing the pointer value back from the function. Try:
void create_int(int **p) {
*p = (int *) malloc(sizeof(int));
}
int main() {
int *p = NULL;
create_int(&p);
assert(p != NULL); /* failed. why? I've allocated memory for it. */
return 0;
}
The variable p in the function create_int is a copy of the variable p in main. So any changes made to p in the called function does not get reflected in main.
To make the change get reflected in main you need to either:
Return the changed value:
int* create_int(int *p) {
p = malloc(sizeof(int));
// err checking
return p:
}
...
// in main:
p = create_int(p);
Or pass the address of p as:
void create_int(int **p) {
*p = malloc(sizeof(int));
// err checking
}
...
// in main:
create_int(&p);
You need a pointer to a pointer like this:
void create_int(int **p)
{
*p = (int *) malloc(sizeof(int));
}
int main()
{
int *p = NULL;
create_int(&p);
assert(p != NULL); /* failed. why? I've allocated memory for it. */
return 0;
}
As folks have pointed out, it's failing since you're not actually changing the pointer that the caller has.
A different way to think about the code might be to notice that it's basically wrapping malloc(), i.e. it's doing a memory allocation but with intelligence added. In that case, why not make it have the same prototype (=call signature) as malloc()? That makes it clearer in the caller's context what's going on, and easier to use:
int * create_int(void)
{
return malloc(sizeof (int));
}
int main(void)
{
int *p = create_int();
assert(p != NULL);
return 0;
}
Also, in C you should never cast the return value of malloc() (see Do I cast the result of malloc?).
You need to send a pointer to a pointer to be able to assign a memory to it via a function
void create_int(int **p)
{
*p = (int*)malloc(sizeof_int));
}
int main()
{
int* p = NULL;
create_int(&p);
assert(p != NULL);
return 0;
}
Your code contains two pointers: one in the create_int function and another one in main. When you call create_int, a copy of the pointer in main is made and used, then eliminated when the create_int function returns.
So, any changes you did to the copy within create_int remain there and are not propagated back to main.
The only way to propagate changes between functions in C (aside from, obviously, returning new values) is to pass a pointer to the changed values. This way, while the pointer being passed will be copied, the value that it points to will be the same, so changes will apply.
Since you're trying to change a pointer, you need a pointer-to-pointer.
void create_int(int **pp)
{
// this changes the pointer that `p` points to.
*pp = (int *) malloc(sizeof(int));
}
int main()
{
int *p = NULL;
// this sends a pointer to the pointer p in main
create_int(&p);
assert(p != NULL);
return 0;
}