I'm compiling a subroutine for a FEA package with ifort 126.96.36.1995 using Visual Studio 2015.
I've managed to set things up so I can set breakpoints in the code and inspect variables at run-time.
I've noticed that when I do this I can see long lists of variables which I know are coming from the FEA software's common blocks that I've included into my subroutine. However when I try to inspect their values, they all say "Undefined variable nodecount" (using nodecount as an example).
If however I do the following...
integer :: nodecount_COPY nodecount_COPY = nodecount
...then I can inspect the value of nodecount_COPY, which has a meaningful value, so I know that nodecount has been defined at some point by the FEA package. (nodecount in this example remains undefined as far as the watch window is concerned).
The files that I am including are all *.cmn files in the FEA software's directory tree. As far as I can tell, they're just text files that define the type of variable (but not dimension). They all refer to common/something/somethingelse
I am compiling with /Od (I also tried /O0 and /Og to no avail)
My only guess is that despite these switches, the compiler is insisting on optimising away these values which are never assigned by me explicitly.
Does anyone have any ideas about how I can access these other variables that are reported as undefined?
Hi andrew_4619, thank you for the reply.
I tried the :: syntax a few times and couldn't get any results. The variable names do appear to show in the watch window by default (they're just all undefined).
For example, when I am debugging a subroutine in my private module namesapce, the difference between a local variable (returnCount) and a variable that has come from an external common block (scaleDisp_CN) displays as shown the following image.
However, I know scaleDisp_CN is defined, since if I copy it, I can see it's value in the watch window.
integer :: scaleDisp_CN_COPY scaleDisp_CN_COPY = scaleDisp_CN
Furthermore, I've tried a few combinations of watch settings, none of which seem to work.
(scaleDisp_CN is defined in spaceco.cmn and spaceco.cmn defines scaleDisp_CN as a child of common/marc_cn_contact4/)
While it's true that you can preface module variables with the module name to find them in the debugger, it's not true that you can do that with common variables.
I can't reproduce the problem you're seeing given this description. Can you reproduce the problem with a smaller, self-contained example that you could share here?
I'll also note that this is an older version of the compiler; it's also possible that a bug was resolved.
thank you --
Hi Lorri, thank you for the reply.
I don't think I will be able to create a small reproduction since it requires the FEA package to run.
I just noticed however that variables declared in one of my include files have their values visible in the watch window.
This doesn't seem to make any sense, all of my includes are coming from the same folder, and as far as I can tell, the files are all setup in the same way.
For example, I have
include 'surfac' ! C:\MSC.Software\Marc\2016.0.0\marc2016\common\surfac.cmn include 'dimen' ! C:\MSC.Software\Marc\2016.0.0\marc2016\common\dimen.cmn
All variable names and values associated with surfac are visible in the locals window but only variable names from dimen are visible (all values are undefined). I've attached these files.
I've tried changing the include order (just in case it was a limit thing) and that had no effect.
This is very strange, but at least we know my configuration is capable of retrieving at least some of these common block values.
I noticed that many of my includes end with this line
!$omp threadprivate(/......[some common block name]....../)
Only surfac didn't. This seemed like too much of a coincidence, so I found another *.cmn file that didn't have this line, included it and sure enough it's values were visible in the locals window.
So then I tried to remove this line from the includes that had it, and found that suddenly values were populated for the includes that had this line removed, however all values were set to zero, so that's no good.
I've done some research but this is all quite beyond me, what does this directive do and is there anything I can do to let Visual Studio overcome whatever limitation this directive imposes?
I think that you have to describe the application and environment precisely.
If the code that you have been describing in this thread is compiled into a DLL that is loaded dynamically by the FEA package, the common block in the FEA executable and the common block in the DLL are going to be distinct unless special care is taken to make the memory allocated common block is shared and synchronized between the DLL and the FEA package.
If, on the other hand, your code is built into an EXE by linking your OBJ files with an FEA static library, the common blocks should work without any special handling being needed.
See the examples provided with the compiler -- there is one that is about sharing data in this fashion.
Thank you for the reply.
The second scenario describes my setup. The code is built into an exe linked to the FEA packages libraries.
Did you see my comment about the threadprivate directive? I suspect that this is significant.
I will look into the examples now and try to develop my understanding.
RE: Threadprivate variables.
Each thread has its own copy of the variable. Which one(s) do you intend to watch?
That was a rhetorical question as I expect the answer to be: Ahhh...
I think you need to re-think your situation and how to achieve the results you want.
Sure no problem, please find the build log attached.
I have the following switches in the command line
I notice that if I remove them, I get the same thing as removing the threadprivate directives from the *.cmn files (all values are populated but set to zero).
I've inherited this command line from the default setup for the FEA package.
>>I notice that if I remove them, I get the same thing as removing the threadprivate directives from the *.cmn files (all values are populated but set to zero).
Then if you are running parallel code, you broke your program.
Do not rely of some other entity to initialize your variables (it is not reliable as you have experienced).
Thanks for the reply, you are indeed correct, the answer is along the lines of "Ahhh..."
The purpose of this exercise is to try and change some settings in the FEA solver interface and see how these are expressed in the common block variables.
As I'm sure is obvious, there are thousands upon thousands of available variables, the vast majority of which are not documented. In this particular instance, I am trying to get a variable that tells me the Length Unit of the user's simulation "meter, millimeter, inch etc".
I started working through each one with a copy value as I documented earlier but quickly gave up. This is my only hope.
In a multi-threaded application, I would make an educated guess, that something like the dimensions of the workspace is a shared variable (IOW not threadprivate). This would exclude anything threadprivate.
I further would assume that the user prepares input data (file or command line arguments) to which you can control candidate inputs. Knowing the input data, and changes from test to test, you should be able to locate the dimensions, and thus discern any conversion factor (e.g. inches to millimeter).
To aid with this, instead of using the debugger, can you add diagnostic code to dump the common data to file (or console window). If not, then use the debugger, open a memory window and use that to explore the common block(s). Note, float and double values should be aligned at natural boundaries. Once you locate the memory address, you can use (generate) the map file to find the common block (and/or block name) then determine the offset into the block. Then using the common statement(s) locate the variable(s).