Community
Participate
Working Groups
Consider the following program: =============================== 1. #include <iostream> 2. #include <cstdlib> 3. using namespace std; 4. 5. typedef struct { 6. int i; 7. char c; 8. } Global; 9. 10. typedef Global* GlobalPtr; 11. 12. GlobalPtr pGlobalPtr; 13. 14. int main() { 15. int i = 0; 16. i++; 17. pGlobalPtr = new Global(); 18. return 0; 19. } =============================== How to reproduce: 1. Create debug configuration in Eclipse Juno SR1. 2. Start debugging 3. <debugger stops at main> 4. Create Breakpoint on line 17. 5. Open Expressions View. 6. Add "pGlobalPtr" into Expressions View. 7. Do "Continue" 8. <debugger stops at line 17> 9. Value of "pGlobalPtr" in Expressions View is equal to 0x0 [Correct]. 10. Do "Step Over" 11. <debugger stops at line 18> 12. Value of "pGlobalPtr" in Expressions View is still equal to 0x0 [Incorrect]. 13. Switch to "gdb Console" 14. Issue command "print pGlobalPtr" to GDB. 15. Observe value returned from GDB to be different than the value in Expressions View. This can be reproduced with Eclipse Indigo and Eclipse Juno with GDB 7.1 and GDB 7.5
I see this too. GDB reports the change in -var-update, so it looks like this is our bug.
The problem is how we parse/handle types. Here is simpler program to reproduce: typedef int* intPtr; int main() { intPtr p = 0; p = (int*)1; return 0; } the expression 'p' will never get updated. The reason is that the MIVariableManager believes that expression cannot change value. This can be seen in the fact that MIVariableObject.isModifiable() returns false for 'p', which is caused by the fact that MIVariableObject.isComplex() returns true because GDBTypeParser could not figure out that this type 'intPtr' is a pointer. GDBTypeParser marks 'intPtr' as a 'generic' type. Maybe that is a special case that MIVariableManager has to handle properly. I'll have to dig some more.
This seemed pretty bad and I started to wonder how come no one reported this before. The reason is that for most 'typedef' types, things will work properly; the cases that won't work are typedefs of pointers or references. In that case, MIVariableManager does not realize they are pointers or references and assumes they are complex structures with no values. This is a regression from the CDI debugger that used GDB's 'ptype' command to figure out what the typedef really represented.
I have been looking at this and have a working fix using "ptype" the same as CDI. However this may not work correctly when debugging multiple processes in one session. There does not seem to be a clean way to execute a CLI command for a specific thread/process, so where there are multiple processes there is no way to ensure "ptype" is in the correct context. As a result it may return results based on the wrong symbol data, although I have not been able to test this. There is an equivalent MI command "-symbol-type" listed in the GDB docs but this does not seem to be implemented. I can push what I have to Gerrit but wanted to confirm this was an acceptable limitation. Or if there was another way I had not considered.
I think this sounds similar to bug 293832 which has a proposed patch.
(In reply to Marc-Andre Laperle from comment #5) > I think this sounds similar to bug 293832 which has a proposed patch. Agreed, that solution also avoids the problems with ptype I mentioned, although is not a complete fix.
For information, you can use a CLI command by extending MIInterpreterExecConsole which will automatically handle thread-selection for the command (using the MI --thread flag)
*** Bug 478324 has been marked as a duplicate of this bug. ***
I've started looking into it. I have noticed that to be considered modifiable (and to be considered for a value update I guess), a MIRootVariableObject needs to be included in its own list of "modifiable descendants". The root varobj corresponding to our pointer did not include itself in this list because isModifiable returned false, because isComplex returned true, because it has a chilren (the pointed value) && CDT doesn't know it's a pointer. So it's considered the same way as a struct would be. Because it's not in the modifiable descendant list, the update is skipped in MIRootVariableObject::processChanges. This little change here, which forces any root varobj to include itself in its modifiable descendant list, fixes this particular problem. This is just to help pinpoint the problem, I have not check collateral damage of that change yet. diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java index 79d9ea4d18..0d54554115 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIVariableManager.java @@ -2203,9 +2203,7 @@ public class MIVariableManager implements ICommandControl { } // If we are modifiable, we should be in our modifiable list - if (isModifiable()) { - addModifiableDescendant(getData().getName(), MIRootVariableObject.this); - } + addModifiableDescendant(getData().getName(), MIRootVariableObject.this); if (localExprInfo.isDynamic() && (localExprInfo.getChildCountLimit() != IMIExpressions.CHILD_COUNT_LIMIT_UNSPECIFIED)) {
Created attachment 266462 [details] First patch
I put the patch as an attachment instead, since bugzilla doesn't preserve text formatting.
New Gerrit change created: https://git.eclipse.org/r/89639
New Gerrit change created: https://git.eclipse.org/r/89795
Gerrit change https://git.eclipse.org/r/89639 was merged to [master]. Commit: http://git.eclipse.org/c/cdt/org.eclipse.cdt.git/commit/?id=9462c1db2421f05ab00e271da33a18d30bac7bbb
Thanks a lot Simon for fixing this! Can you double check the New and Noteworthy entry I added? Thanks! https://wiki.eclipse.org/CDT/User/NewIn93#API_modifications