|
It is currently Thu Feb 09, 2012 12:16 am
|
View unanswered posts | View active topics
| Welcome |
|
Welcome to RHAPSODY4YOU
You are currently viewing our boards as a guest, which gives you limited access to view most discussions and access our other features. By joining our free community, you will have access to post topics, respond to polls, upload and download content, and access many other special features. Registration is fast, simple, and absolutely free, so please, register to join our community today. |
 |
|
 |
|
| Author |
Message |
|
bitblit
|
Post subject: Initial instances causing crash Posted: Thu Jun 25, 2009 3:18 pm |
Joined: Wed Dec 10, 2008 10:51 pm Posts: 138
|
|
I've attached a simple model that recreates a problem we ran into. Basically, a member function of a class that is instantiated in "Initial instances", is calling a function on an object that is created in an Object Diagram (and shows in the browser as itsClassA), but fails on the call to another object created in an Object Diagram (and shows in the borwser as itsClassB).
When the first object is instantiated in the Object Diagram, rather than in "Initial instances", everything works just fine.
itsClassA - Instantiated in Object Diagram
itsClassB - Instantiated in Object Diagram
itsTestStub - Instantiated in Object Diagram
p_TestStub2 - Instantiated in "Initial instances"
itsTestClass.runTest() ---> itsClassA.process40Hz() ---> itsClassB.process40Hz Works!
p_TestStub2 ---> itsClassA.process40Hz() ---> itsClassB.process40Hz Crashes on the second hop
Tracing through the code shows that the second call on itsClassB is on a null pointer. What I don't understand is that I can step through the code in VS and see the pointer is set correctly. But when it gets to that function call, the pointer is null.
I now know not to get myself in this situation, and what to do when it is. I just don't know why this happens.
|
|
|
|
 |
|
Farquad
|
Post subject: Posted: Thu Jun 25, 2009 7:12 pm |
Joined: Thu Sep 13, 2007 7:34 pm Posts: 397 Location: London
|
|
Your problem here is a simple misunderstanding of how Rhapsody works. The object diagram does more than just instantiate the objects. You have links on there. These also get instantiated. The relationship from p_TestStub2 to ClassA is never instantiated. It may appear to be on the second hop but the first hop fails too.
I've attached an example that show various ways of instantiating your logical model. Note the Scope tab in the components.
| Attachments: |
File comment: Instantiation Options
supportZip.zip [42.99 KiB]
Downloaded 87 times
|
|
|
|
|
 |
|
bitblit
|
Post subject: Posted: Thu Jun 25, 2009 9:26 pm |
Joined: Wed Dec 10, 2008 10:51 pm Posts: 138
|
|
Also, I still don't see why it failed on the call from ClassA to ClassB, and not from TestStub to ClassA. ClassA to ClassB were instantiated in object diagrams, and had the pointer set correctly. TestStub2 was not. The pointer between TestStub2 and ClassA was not set, so how was it able to still call the process40Hz function in ClassA, and fail there?
Last edited by bitblit on Thu Jun 25, 2009 10:17 pm, edited 1 time in total.
|
|
|
|
 |
|
Farquad
|
Post subject: Posted: Thu Jun 25, 2009 10:00 pm |
Joined: Thu Sep 13, 2007 7:34 pm Posts: 397 Location: London
|
|
I think that's because it didn't actually try and run any code until the second hop. Also, perhaps the first hop was defaulted to an address it could access.
|
|
|
|
 |
|
bitblit
|
Post subject: Posted: Fri Jun 26, 2009 3:23 am |
Joined: Wed Dec 10, 2008 10:51 pm Posts: 138
|
|
I figured it out. Either Visual Studio builds code differently, or I've just never noticed what really happens during a function call. I even verified this in just plain Visual C++ 2005 Express, without Rhapsody.
You can call a function on a null pointer. It will execute the function that the pointer is supposed to be, even its actually null. Any access to a member attribute within this function call will fail. This is because it separates code space from data space. The code is the same for n number of objects you instantiate. So, only one copy of the code exists. Many different sets of member attributes can exist, so it keeps these copies in a separate place.
When you call a function call on a null pointer, execution will jump from the caller, to the virtual table, into the called function call code space. It executes from the only copy that ever exists. However, when you try to access a member attribute, it retrieves the address to the actual data space with the values. So, the first hop executes, or at least starts execution. However, it must read the pointer to the next hop and since the first call was null, there is no copy of data space, and no copy of the pointer. The assembly to retrieve the pointer from data space, retrieves a null instead. This is where the error occurs.
So, its not really that you try to call a function on a null pointer, that causes the problem. That actually executes. The error is because it doesn't have a handle to an object, so it can't access the pointer member attribute.
I had to step through a bunch of assembly to figure it out. To prove it, write a C++ app where ClassA calls a function on ClassB. Instantiate both classes (itsClassA and itsClassB). Add member pointer attributes in ClassA that points to an object of ClassB, but DO NOT realize the association or set the pointer. Now, call a function from ClassA onto ClassB via the uninitialized pointer to ClassB. Make sure the function call does not access any member attributes. I just printf'd some text. Even though the pointer is null, it will execute with no errors.
|
|
|
|
 |
|
|
 |
|
 |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|
|