Hi Doug,
There is a good tool called dependency walker http://www.dependencywalker.com/ that will show exactly which DLLs are referenced by other DLLs/executables - might be worth running this and checking everything is as you think it should be. You can get strange crashes in programs that load multiple versions of the MSVC library - it's not automatically a problem, but if resources are allocated in a DLL using one library version and then passed to and freed in a DLL using another library version then that can lead to a crash.
Regards,
Freddie
> -----Original Message-----
> From: [email protected] [mailto:[email protected]]
> Sent: 07 May 2015 19:56
> To: Akeroyd, Freddie (STFC,RAL,ISIS)
> Cc: [email protected]; [email protected]
> Subject: RE: Problems using static database routines to modify IOCs
>
> Hi Freddie,
>
> Thank you for spending time looking at this for me. Unfortunately, I'm
> still having the issue. I get access violations from several dlls not just
> dbStaticHost.dll and they all involve a string function call. I checked
> into what you found out and I believe I'm only building against the IOC
> libraries but the code is built as a MS Visual Studio project which I have
> almost no experience with, so I'm not certain.
>
> Here's what I have learned over the week.
>
> I decided to try to add the database dump code to the example IOC
> application that comes with EPICS.
>
> First I booted my Scientific Linux partition and built the example IOC
> with gcc. After I tested the IOC I added the dump code to the IOC Main and
> recompiled. The modified code worked perfectly.
>
> Next, I booted Windows 8 and built EPICS with the MS Visual Studio 2012
> compiler. I then built the example IOC and ran it successfully. I added
> the dump routine to Main and recompiled and again the IOC ran flawlessly.
>
> Finally, I went to the test computer I've been working on, Windows 7 32
> bit. EPICS was built on it using MS VS 2012. I built the example IOC again
> and it ran with no issues. I added the dump routine and recompiled and it
> ran with no problems!
>
> So it appears that the problem I'm having is in one of two things or maybe
> both. Either there is a problem in the already modified IOC code that I'm
> trying to add this dump routine to, or there is a problem with the way the
> IOC is built. In all my successes I used the make files, but the IOC I'm
> working on is saved as a MS VS project.
>
> So at this point I'm trying to build the example IOC as a MS VS project,
> so that I can learn about Visual Studio. Once that works I'll look at the
> IOC code that was added before I worked on this. I know one routine that
> was added converts TwinCAT PLC files into db files which are then used by
> the IOC. So maybe there is something in that routine that causes an error
> in the global pdbbase at initialization.
>
> It's strange though because pdbbase works fine within the IOC once the
> shell is running, I can use all of the built in db routines with no
> issues. It's only during initialization that this error occurs.
>
> In any case at least I feel like I have direction rather than blankly
> staring at code that 'should' work!
>
> Thank you all again for your time, suggestions, and guidance,
> Doug Lormand
>
>
> > Hi Doug,
> >
> > I've managed to reproduce your problem - it was a bit confusing at first
> > as your example worked fine for me, but then I recalled that in your
> > original message the crash was in dbStaticHost.dll rather than
> > dbStaticIoc.dll
> >
> > "Unhandled exception at 0x5C6F1C6E (dbStaticHost.dll) in tcIoc.exe:
> > 0xC0000005: Access violation reading location 0x00000031."
> >
> > Running a dependency walker on my test IOC showed neither a direct nor
> > indirect reference to this DLL. I changed my IOC Makefile LIBS line from:
> >
> > $(APPNAME)_LIBS += $(EPICS_BASE_IOC_LIBS)
> >
> > to:
> >
> > $(APPNAME)_LIBS += $(EPICS_BASE_HOST_LIBS)
> $(EPICS_BASE_IOC_LIBS)
> >
> > and then I had a crash at dbGetString() in dbStaticHost.dll So I'm
> > guessing you are linking against both HOST and IOC libraries and you just
> > need to remove references to the HOST libraries from your Makefile for it
> > to work
> >
> > Regards,
> >
> > Freddie
> >
> >> -----Original Message-----
> >> From: [email protected] [mailto:tech-talk-
> >> [email protected]] On Behalf Of [email protected]
> >> Sent: 01 May 2015 23:59
> >> To: Andrew Johnson
> >> Cc: [email protected]; EPICS
> >> Subject: Re: Problems using static database routines to modify IOCs
> >>
> >> Hello Andrew and Tim,
> >>
> >> Ok here's what I am attempting to do.
> >>
> >> The goal is at IOC startup after initialization to be able to compare a
> >> set of channel values with a saved set of values, so that any
> >> differences
> >> can be investigated.
> >>
> >> The IOC I am tying to modify is running on a Windows 7 computer and I'm
> >> using Visual Studio 2012 update 4.
> >>
> >> The first step in this was to modify the Windows IOC so that it would
> >> perform a database dump to standard output right before the ioc shell is
> >> invoked. This was really just to get some experience modifying and
> >> working
> >> with IOC code.
> >>
> >> So I took the iocMain.cpp and literally copied the dbDumpRecords
> example
> >> function at the end of the EPICS application developer's guide, chapter
> >> 14.16.2. After adding that function prototype and the function to the
> >> iocMain.cpp, I am trying to call the function in main() right before the
> >> iocsh(NULL) call.
> >>
> >> Everything compiles ok but I am clearly not pointing to the right place
> >> since I get garbage plus the IOC crashes. The only way it works was to
> >> load a second instance of the database into memory which you are right
> >> is
> >> not what I want to do.
> >>
> >> Here is the iocMain.cpp code,
> >>
> >>
> >>
> >> #include "epicsExit.h"
> >> #include "epicsThread.h"
> >> #include "iocsh.h"
> >> #include <ctime>
> >> #include "dbAccess.h"
> >> #include "dbStaticLib.h"
> >> #include "dbDefs.h"
> >> #include "dbFldTypes.h"
> >> #include "link.h"
> >>
> >> extern "C" {
> >> __declspec(dllimport) void stopPLCs(void);
> >> }
> >>
> >> // Function proto types
> >> ************************************************
> >>
> >> void dbDumpRecords(DBBASE *); //
> >> code I added <---------------------
> >>
> >> // Function definitions
> >> ************************************************
> >>
> >> // code I added here
> >> <--------------------------------------------------------------------------------
> >>
> >> void dbDumpRecords(DBBASE *pdbbase)
> >> {
> >> DBENTRY *pdbentry;
> >> long status;
> >>
> >> mypdbentry = dbAllocEntry(pdbbase);
> >>
> >> status = dbFirstRecordType(pdbentry);
> >> if(status) {printf("No record descriptions\n");return;}
> >> while(!status) {
> >> printf("\nRecord type:
> >> %s",dbGetRecordTypeName(pdbentry));
> >> status = dbFirstRecord(pdbentry);
> >> if(status) printf(" No Records\n");
> >> while(!status) {
> >> if (dbIsAlias(pdbentry)) {
> >> printf("\n Alias:
> >> %s\n",dbGetRecordName(pdbentry));
> >> } else {
> >> printf("\n Record:
> >> %s\n",dbGetRecordName(pdbentry));
> >> status = dbFirstField(pdbentry,TRUE);
> >> if(status) printf(" No Fields\n");
> >> while(!status) {
> >> printf(" %s:",dbGetFieldName(pdbentry));
> >> printf(" %s\n",dbGetString(pdbentry)); //
> >> <-- if I comment out
> >> dbGetString the IOC doesn't crash,
> >> status=dbNextField(pdbentry,TRUE); //
> >> so the function works
> >> to this point
> >> }
> >> }
> >> status = dbNextRecord(pdbentry);
> >> }
> >> status = dbNextRecordType(pdbentry);
> >> }
> >>
> >> printf("\nEnd of all Records\n");
> >>
> >> dbFreeEntry(pdbentry);
> >> }
> >> // end of function that I added
> >> <---------------------------------------------------------------------
> >>
> >> // Time the initialization process
> >> clock_t begin;
> >> clock_t end;
> >>
> >> /** @file iocMain.cpp
> >> The main program for the TwinCAT IOC.
> >>
> >>
> **************************************************************
> >> **********/
> >>
> >>
> >> bool debug;
> >>
> >> int main(int argc,char *argv[])
> >> {
> >> // Start timer
> >> begin = clock();
> >>
> >> // Run initialization
> >> if(argc>=2) {
> >> iocsh(argv[1]);
> >> epicsThreadSleep(.2);
> >> }
> >>
> >> // Stop timer
> >> end = clock();
> >> printf("Initialization completed in %f seconds.\n",((float)(end -
> >> begin)/CLOCKS_PER_SEC));
> >>
> >>
> >> // Test routine
> >>
> **************************************************************
> >> ****
> >>
> >> // code I added
> >> <---------------------------------------------------------------------------------
> >>
> >> printf("\nRecords dump **********************\n");
> >>
> >> dbDumpRecords(*iocshPpdbbase); // Trying to call function here!
> >>
> >> // end of code that I added
> >> <---------------------------------------------------------------------
> >>
> >> // EPICS command line
> >> iocsh(NULL);
> >>
> >> // Exit
> >> stopPLCs();
> >> epicsExit(0);
> >>
> >> return(0);
> >> }
> >>
> >> To do a value comparison I think I'll need to use the runtime access
> >> routines in addition to some of the static routines. But at this point
> >> I'm
> >> not sure of anything. I have been trying to understand and copy code
> >> from
> >> the functions in dbtools.c and dbStaticLib.c but so far nothing has
> >> worked
> >> for me.
> >>
> >> I'm sorry to be such a problem, been staring at this for four weeks now
> >> and am at my wits end.
> >>
> >> Thank you in advance,
> >>
> >> Doug Lormand
> >>
> >> > Hi Doug,
> >> >
> >> >> The system is a Windows 7 computer! Unfortunately I need this to
> work
> >> in
> >> >> Windows because the software we use the IOC for is only Windows
> >> based.
> >> >> Thank you for pointing this out since I hadn't considered it could be
> >> a
> >> >> Windows compatibility issue. The ultimate goal is to use database
> >> access
> >> >> to compare values at boot up with a set of stored 'good' values. I
> >> think
> >> >> this will require the runtime database access routines which I've had
> >> >> some
> >> >> success with so far. So in the end I'm hoping this might be a non
> >> issue.
> >> >
> >> > Doing this on Windows should not be a problem. To clarify, you're
> >> > wanting to compare these values *before* the IOC runs iocInit()?
> >> >
> >> >>>> I have been able to get the example code to work within the IOC I'm
> >> >>>> trying
> >> >>>> to modify, but in a round about way. It is some type of pointer
> >> >>>> problem
> >> >>>> but I'm not sure what's wrong.
> >> >>>>
> >> >>>> So the code works if I add the following,
> >> >>>>
> >> >>>> void dbDumpRecords(DBBASE *pdbbase)
> >> >>>> {
> >> >>>> DBENTRY *pdbentry;
> >> >>>> long status;
> >> >>>>
> >> >>>> status =
> >> >>>>
> >>
> dbReadDatabase(&pdbbase,"C:\\SlowControls\\EPICS\\Utilities\\Bin\\tCat.d
> >> bd",NULL,NULL);
> >> >>>> if(!status) {printf("Database file loaded.\n");}
> >> >>>> else {printf("Database load file failed.\n");}
> >> >>>>
> >> >>>> status =
> >> >>>>
> >>
> dbReadDatabase(&pdbbase,"C:\\SlowControls\\EPICS\\Utilities\\Bin\\test.d
> >> b",NULL,NULL);
> >> >>>> if(!status) {printf("Records file loaded.\n\n");}
> >> >>>> else {printf("Records load file failed.\n\n");}
> >> >>>>
> >> >>>> pdbentry = dbAllocEntry(pdbbase);
> >> >>>> .......rest of dump routine
> >> >>>>
> >> >>>> So the dump routine runs perfectly if I include dbReadDatabase
> >> >>>> routines
> >> >>>> for both the database.dbd and records.db files.
> >> >
> >> > What that is doing is loading a second instance of the database
> >> > definition into memory, which is not what you want to do.
> >> >
> >> >>>> What I don't understand is why I need to Read the databases into
> >> the
> >> >>>> function separately from the IOCs initialization. I thought I could
> >> >>>> access the runtime database in memory through pdbbase.
> >> >
> >> > You should be able to, so the fact that you're having problems tells
> >> me
> >> > that the pdbbase pointer that your code is using is not the same one
> >> > that the IOC is using. The dbStatic library is designed to allow
> >> > multiple databases to be loaded into memory at once, but the IOC can
> >> > only run one, which is declared in the header dbAccessDefs.h (also
> >> > included by dbAccess.h).
> >> >
> >> >>>>>> The code solution compiles without any issues but when I try to
> >> run
> >> >>>>>> the
> >> >>>> IOC it causes the following
> >> >>>>>> Unhandled exception at 0x5C6F1C6E (dbStaticHost.dll) in
> >> tcIoc.exe:
> >> >>>> 0xC0000005: Access violation reading location 0x00000031.
> >> >
> >> > That might have been that you were accessing iocshPpdbbase or
> pdbbase
> >> > before it was initialized. I'd need to see your iocMain.c to be sure,
> >> > but in general you should be running this kind of code from the
> >> startup
> >> > script using a command that your code registers with iocsh, or from an
> >> > initHook. That way it can be run at the right time, which would be
> >> after
> >> > the dbLoadDatabase() and dbLoadRecords() commands but before
> iocInit()
> >> > starts up the database operations.
> >> >
> >> >
> >> > Lets try starting from the beginning again: You're wanting to "compare
> >> > values at boot up with a set of stored 'good' values". As Tim said
> >> there
> >> > are some fields (mostly array fields) for which you can only do that
> >> > from an initHook as part of the IOC startup, but for most fields you
> >> can
> >> > do it earlier, as long as the database definition and record instances
> >> > have been loaded first.
> >> >
> >> > How & when are you running your code?
> >> >
> >> > - Andrew
> >> >
> >> > --
> >> > Light thinks it travels faster than anything but it is wrong.
> >> > No matter how fast light travels, it finds the darkness has
> >> > always got there first, and is waiting for it.
> >> > -- Terry Pratchett, Reaper Man
> >> >
> >>
> >
> >
>
- References:
- Re: Problems using static database routines to modify IOCs Dirk Zimoch
- Re: Problems using static database routines to modify IOCs marc . lormand
- RE: Problems using static database routines to modify IOCs Mooney, Tim M.
- Re: Problems using static database routines to modify IOCs Andrew Johnson
- Re: Problems using static database routines to modify IOCs marc . lormand
- RE: Problems using static database routines to modify IOCs freddie.akeroyd
- RE: Problems using static database routines to modify IOCs marc . lormand
- Navigate by Date:
- Prev:
RE: Problems using static database routines to modify IOCs marc . lormand
- Next:
Final Program for the Spring 2015 EPICS Collaboration Meeting Maxwell, Dylan
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
<2015>
2016
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
RE: Problems using static database routines to modify IOCs marc . lormand
- Next:
Gentec S-link power meter problem with ending I/O interrupt measurement bohmm
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
<2015>
2016
2017
2018
2019
2020
2021
2022
2023
2024
|