www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Pointer cast to uint and back: segfault

reply Frank Benoit <frank_DELETE_ _DELETE_drealtime.com> writes:
I have a class which is not managed by the gc. This is done like in the
example on http://digitalmars.com/d/memory.html#newdelete 
Now I need to transfer these object-references through a queue.

If I write this:

union U
{ uint val;
  Cls  obj;
}

// obj -> uint
U u;
u.obj = obj;
queue.push( u.val );
        
// uint -> obj
U u;
u.val = queue.get();
u.obj.doSomething();

... it works excellent. But now i want to make this with directly casting to
the right type without the intermediate copy to a union. 

// obj -> uint
queue.push( cast(uint)(&obj) );

// uint -> obj
Cls obj = *cast(Cls*)( queue.get() );
obj.doSomething(); // segmentation fault

Whats wrong? I am pretty sure my queues are working correctly.

////////////////////////////////////////////////////////////////////////
/// The following is a description of further experiments:
////////////////////////////////////////////////////////////////////////
... So I made a little test program:

class C { 
  void doIt() { writefln( "yes" ); }
}

void main(){
  C c = new C;
  uint u = cast(uint)(& c );
  ( *cast(C*)(u) ).doIt();
}

No segfault. :( 
Playing with it I get another segmentation fault when I made functions for
the casts and inserted a writefln:

uint toUint( C c ){
  uint r = cast(uint)(& c );
  return r;
}

C toC( uint u ){
  return *cast(C*)(u);
}

void main(){
  uint u = toUint( new C );
  writefln( "%08x", u );
  toC( u ).doIt(); // Segfault
}
  

By the way: This compiles
uint toUint( C c ){
  uint r = cast(uint)(& c );
  return r;
}

This not:
uint toUint( C c ){
  return cast(uint)(& c ); // escaping reference to local c
}


Frank

-- 
D goes real-time: http://www.drealtime.com
Feb 17 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Frank Benoit" <frank_DELETE_ _DELETE_drealtime.com> wrote in message 
news:dt5jp4$p97$1 digitaldaemon.com...

Two things.  Class references are already at one level of indirection. 
Taking the address of a class reference won't work the way you think. 
That's why your functions won't work; that "escaping reference to local" 
error was trying to help you.  You're not returning the address of the 
object held in c; you're returning the address of a local variable c, which 
is on the stack and becomes invalid when the function returns.  So instead 
of getting the address, just use cast(uint)cast(void*)new C, and get it back 
with cast(C)cast(void*)(u).

The second thing is I can't figure out why the hell you have to do all this. 
Can't you make your queue accept class references? 
Feb 17 2006
parent reply Frank Benoit <frank_DELETE_ _DELETE_drealtime.com> writes:
Thanks, that was the cast I was looking for.

 The second thing is I can't figure out why the hell you have to do all
 this. Can't you make your queue accept class references?
Yes perhaps this would be possible, but in my case this is the straight way, I think. To give you an idea what I am doing. I use a real-time extension for Linux. Threads running in real-time could not allocate dynamic memory. But I want to generate test results. So I use a queue with a fixed size ring buffer. A code generator makes functions for me, doing the encoding of the defined message types. Putting all data in the uint array of the queue. On the other side (in the normal, not-real-time thread) there is also generated code, decoding the data, creating objects with the right type and calling "new" and filling them with the data of the queue. But to pass object through such a queue, they have to be casted to raw data. Thanks for your help Frank -- D goes real-time: http://www.drealtime.com
Feb 17 2006
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Frank Benoit" <frank_DELETE_ _DELETE_drealtime.com> wrote in message 
news:dt5phm$tk8$1 digitaldaemon.com...
 To give you an idea what I am doing. I use a real-time extension for 
 Linux.
 Threads running in real-time could not allocate dynamic memory. But I want
 to generate test results. So I use a queue with a fixed size ring buffer.
 A code generator makes functions for me, doing the encoding of the defined
 message types. Putting all data in the uint array of the queue.
 On the other side (in the normal, not-real-time thread) there is also
 generated code, decoding the data, creating objects with the right type 
 and
 calling "new" and filling them with the data of the queue. But to pass
 object through such a queue, they have to be casted to raw data.
Ahh, that makes sense then :)
Feb 17 2006