views:

2329

answers:

9

Hi,

I have a structure

typedef struct my_s {

   int x;
   ...
} my_T;

my_t * p_my_t;

I want to set the address of p_my_t to NULL, tried:

memset (&p_my_t, 0, sizeof(my_t*))

This does not look right,

what is the correct way of doing this? appreciate it...


Amendment to question - asking a radically more complex question:

Thanks, here is what I am trying to do:

  • Two processes, A and B
  • malloc p_my_t in A, B has N threads and can access it
  • Start deleting in A but I can not simply free it since threads in B may still using it.
  • So I call a function, pass address of p_my_t to B to set its address to NULL in B so no other threads in B can use anymore
  • After call back from B, I then free memory in A

NB: there is no standard way to manage memory allocations via shared memory between processes. You will have to do some rather careful thinking about what is going on.

+12  A: 

Don't use memset to initialize a null pointer as this will set the memory to all bits zero which is not guaranteed to be the representation of a null pointer, just do this:

p_my_t = NULL;

or the equivalent:

p_my_t = 0;
Robert Gamble
Recommended code is usually using 0 directly instead of NULL. 0 is just as expressive as NULL and it does not require the macro or its definition.
David Rodríguez - dribeas
Recommended by who? 0 is not as "expressive" as NULL, i = NULL makes it clear that i is a pointer, i = 0 doesn't.
Robert Gamble
In C++, NULL is defined to be 0, so the "i = NULL makes it clear that i is a pointer" is not enforced by the compiler. C++0x has nullptr, and that is indeed enforced.
Chris Jester-Young
The point is that it makes it clear to the human reading your code.
Robert Gamble
It is better to use NULL. It is more readable and, in the slim chance that the definition of NULL changes, your code will not break.
Ed Swangren
I agree with using NULL, but the definition of NULL will not change. It is required by the standard to be 0 (although that may not correspond to setting all bits to zero, as Robert Gamble pointed out)
jalf
The standard guarantees that 0 will be converted to the correct bit-pattern for a null pointer. It says nothing about NULL. NULL is just there for backward compatibility with C code.
Ferruccio
@Ferruccio: Don't be silly, if NULL is defined as 0 then i = NULL will be turned into i = 0 by the preprocessor with the same guarantee as if it were written as i = 0 to begin with.
Robert Gamble
Updated answer to include both versions.
Robert Gamble
The memset and uninitialized static/global variable for NULL has become so common that any new architectures will dare not violate it.
Joshua
@jalf: I agree that NULL won't likely change but this reminds me of the famous quote from the Xerox Fortran manual when discussing the advantages of using the DATA statement (which is similar to using a preprocessor macro):
Robert Gamble
"Instead of referring to PI as 3.141592653589797, at every appearance,the variable PI can be given that value with a DATA statement, andused instead of the longer form of the constant. This also simplifiesmodifying the program, should the value of PI change."
Robert Gamble
@Joshua: 1) In my experience it isn't at all common to use memset to initialize pointer variables, and 2) uninitialized static/global pointer variables are guaranteed to be initialized to NULL in C, I assume the same is true in C++.
Robert Gamble
Why the down-vote? At least explain what is wrong with the answer.
Robert Gamble
i would say neither NULL nor 0 is better. points can be made for either one. some people prefer 0, some prefer NULL. and yeah uninitialized static storage is initialized with NULL in C++ too, and not all bits 0 necassary.
Johannes Schaub - litb
Stroustrup doesn't use NULL. And if you're going to use a macro, as he points out, why would you use NULL instead of the forward looking nullptr???
ApplePieIsGood
Arguments for using NULL have already been well made here. The bottom line is that NULL and 0 both work on all platforms *today*, there is nothing wrong with either one, your downvote is petty.
Robert Gamble
The problem with not using a more expressive form than 0 is that it takes more effort for the human who has to maintain the code to understand the usage. Are you setting a number, pointer, character etc. to 0? nullptr seems like the win from now on.
Greg Domjan
+4  A: 

What exactly are you trying to do? p_my_t is already a pointer, but you haven't allocated memory for it. If you want to set the pointer to NULL, simply do

p_my_t = NULL;

Trying to dereference this pointer will result in a segmentation fault (or access violation on Windows).

Once the pointer actually pointers to something (e.g. via malloc() or by assigning to it the address of a struct my_T), then you can properly memset() it:

memset(p_my_t, 0, sizeof(struct my_T));

This will zero out the entire structure, setting all fields to zero.

Adam Rosenfield
thanks, adding comments here has limitation, so please see my "answer posting"
A: 

Thanks, here is what I an trying to do

  • two processes, A and B
  • malloc p_my_t in A, B has N threads and can access it
  • start deleting in A but I can not simply free it since threads in B may still using.
  • so I call a function, pass address of p_my_t to B to set its address to NULL in B so no others threads in B can use anymore
  • After call back from B, I then free memory in A
you should probably add this info to your question, or rephrase it - however it doesn't sound right as you've described it here. Unless the pointer is to shared memory, how can it be shared across processes?
frankodwyer
I agree this is different than the original question. You should pose this as a separate question, since the answer to the question you actually asked is just p_my_t = NULL;
bsruth
@dave: how do the two processes get to share the memory? This is a vastly different question from what you originally asked.
Jonathan Leffler
A: 

Per your reply (elsewhere in this post) stating:

Thanks, here is what I an trying to do

  • two processes, A and B
  • malloc p_my_t in A, B has N threads and can access it
  • start deleting in A but I can not simply free it since threads in B may still using.
  • so I call a function, pass address of p_my_t to B to set its address to NULL in B so no others threads in B can use anymore
  • After call back from B, I then free memory in A

What you need is some form of synchronization between all your threads and processes. I'm not sure of how you are sharing this object between processes, but I suspect you are using shared memory.

Normally I would recommend using a shared pointer class (such as Boost's shared_ptr class), but I'm not sure of how well that would work in this scenario. You may want to consider tweaking your class so that it tracks its own references and can be used with the Boost intrusive_ptr class.

That way, process A can simply forget about the object, and when process B is finished, the instance of my_T will know that there are no more references left and clean itself up.

The synchronization would come into play here when my_T is adding or removing references internally (so you don't run into nasty race conditions where it thinks it should clean itself up but is really still in use).

One other approach that has a bit more of a "kluge" feel to it is to give each instance of my_T an "is-valid" flag so that all processes/threads using it will know whether or not to continue doing so.

For more details on Boost's various pointer classes, check out their documentation.

Brian
You could also use the TR1 shared_ptr class that was previously available in boost. This will allow you to delete the pointer in B without worrying what A is doing. More information on shared_ptr: http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/shared_ptr.htm
bsruth
+2  A: 

The recommended code for setting a pointer to null is assigning 0 (zero). Bjarne Stroustrup does it :) Anyway it is just as expressive as NULL and does not depend on a macro definition.

Note that NULL is not a keyword, it is not reserved and while it would be confusing to redefine, nothing says that you should not (more than style). A coworker often jokes about defining NULL to something different than 0 in some header just to see how other people's code behave.

In the upcoming standard there will be a more expressive nullptr keyword to identify a null pointer.

David Rodríguez - dribeas
actually, it effectively forbids redefining NULL. you are not allowed to #undef NULL because it is reserved once you include a std header that defines it.
Johannes Schaub - litb
NULL is better! The next c++ standard will have a new object nullptr. There are issues when using 0 (converting an int to a pointer), nullptr will solve them. In gcc NULL is defined as __null. Once nullptr becomes standard, change NULL from 0 to nullptr; all the benefits with no changes for you.
caspin
A: 

I think maybe you want

extern void set_t_pointer_to_null(my_T *pp);

and call

set_t_pointer_to_null(&p_my_t);

where

void set_t_pointer_to_null(my_T *pp) { *pp = NULL; }

I'm not sure it's worth defining a function to do this, but I think this answers the question you're trying to ask.

Norman Ramsey
A: 

From reading your multi-thread comments I should say there is no safe sequence of code to accomplish your task. You will have to step back and reexamine your algorithm.

Joshua
A: 

If I get it right, memset won't solve your problem. If A and B are separate processes, then p_my_t in process A will be different form p_my_t in process B. You just can't pass a pointer between different processes. I sugest you use some kind of IPC mechanism in order to sinchronyze your two processes (message queues, for example), and just using p_my_t = NULL instead of memset.

Marc
A: 

Per your update, it seems to me that what you are really trying to do is guard access to a resource, which means you should use a read/write lock that is shared between the processes to guard the ptr to that resource, and test the ptr before using.

  • Allocate the structure in shared memory.
  • Allocate the ptr to the structure in shared memory.
  • Guard access to the ptr to the structure with a Read/Write lock.
  • Process A should acquire a WRITE lock to the ptr when initializing or invalidating the ptr and structure.
  • Process B should acquire a READ lock to the ptr, and test that the ptr is valid before using the structure
Sanjaya R