Solved

Protected Memory Exception

Posted on 2006-12-01
12
260 Views
Last Modified: 2010-04-16
I have an application that is giving me the following exception :
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

I think it has something to do with the fact that I am making calls to unmanaged code through interop.  I never had this problem until I started doing the interops through background workers.  I am trying to transverse a directories and files and read one type of file in order to load it into a table in a mysql database.  These files I am trying to read and load into the table are of a custom file type.  It takes the code written in C++ to open and read the files, therefore I have to make the calls through interop.  Because there are so many directories I start off 30 Background workers and continuously start each one with a directory to process.  So I know there are constant hits to the interop and dll that the interop is accessing.  Here is my code...

Here is the method that keeps crashing with the exception:
private DataTable SpreadtoTable()
            {
            int ptr = -1;
            try
            {
                int lrc, lrr;
                int[] cols, wids;
                StringBuilder line = new StringBuilder(81);
                StringBuilder lineatt = new StringBuilder(128);

                DataTable dtSpread = new DataTable();

                ptr = SpreadClass.read_spread(mPath);
                if (ptr == 0 || ptr == -1)
                    return null;

                lrr = SpreadClass.get_LRR(ptr);
                lrc = SpreadClass.get_LRC(ptr);
                cols = new int[lrc];
                wids = new int[lrc];

                SpreadClass.get_col_indexs(ptr, cols, wids);

                for (int k = 1; k <= lrc; k++)
                {
                    SpreadClass.get_column_attr(ptr, "Column Name", cols[k - 1], line, lineatt);
                    if (line.ToString().ToUpper() == "DATE")
                        dtSpread.Columns.Add(line.ToString(), Type.GetType("System.DateTime"));
                    else
                        dtSpread.Columns.Add(line.ToString());
                }

                for (int i = 1; i <= lrr; i++)
                {
                    DataRow dr = dtSpread.NewRow();

                    for (int j = 1; j <= lrc; j++)
                    {
                        SpreadClass.getraw(ptr, i, cols[j - 1], line, lineatt);
                        dr[j - 1] = line.ToString();
                    }

                    dtSpread.Rows.Add(dr);
                }
                SpreadClass.deletedb(ptr);
                return dtSpread;
            }
            catch (Exception ex)
            {
                StreamWriter sw = new StreamWriter(spreadLog, true);
                FileInfo fi = new FileInfo(mPath);
                sw.WriteLine(ex.Message + " = " + fi.DirectoryName + " - Unable to convert Master.Cat to table");
                sw.Close();
                return null;
            }
            finally
            {
                SpreadClass.deletedb(ptr);
            }
}

Here are my DllImports:
            [DllImport("spread.dll")]
            public static extern int read_spread(string      fname);

            [DllImport("spread.dll")]
            public static extern void getraw(int ptr, int row, int col,
                  [MarshalAs(UnmanagedType.LPStr)]StringBuilder str,
                  [MarshalAs(UnmanagedType.LPStr)]StringBuilder stratt);

            [DllImport("spread.dll")]
            public static extern int get_LRC(int file);

            [DllImport("spread.dll")]
            public static extern int get_LRR(int file);

            [DllImport("spread.dll")]
            public static extern void get_column_attr(int ptr, string headatt,
                  int column,
                  [MarshalAs(UnmanagedType.LPStr)]StringBuilder str,
                  [MarshalAs(UnmanagedType.LPStr)]StringBuilder stratt);


Here is the C Code            
/****************************************************************************/
long int read_spread ( fname )
char             *fname;
{
}

/****************************************************************************/
getraw ( dbptr, row, col, str, stratt )
long int    dbptr;
int         row;
int         col;
char        *str;
char        *stratt;
{
}

/****************************************************************************/
get_LRC(fileptr)
long int fileptr;
{
}

/****************************************************************************/
get_LRR(fileptr)
long int fileptr;
{
}

/****************************************************************************/
get_column_attr ( dbptr, colatt, col, str, stratt )
long int    dbptr;
char        *colatt;
int         col;
char        *str;
char        *stratt;
{
}

I know that this is a lot to read and look at, but any advice will be greatly appreciated....

Thanks,
Kendal

0
Comment
Question by:gvector1
  • 6
  • 6
12 Comments
 
LVL 48

Expert Comment

by:AlexFM
ID: 18058875
Can you show exactly what C# line gives exception?
0
 

Author Comment

by:gvector1
ID: 18068909
It is the SpreadClass.deletedb(ptr).  This is where the memory is where the pointer to the file is disposed of and the memory released.  It has always worked fine until now.  I was kind of thinking that it may have something to do with my threading.  What do you think?????
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 18069203
SpreadClass.deletedb(ptr);

This line is executed twice - in try block and in finally block. Remove it from try block.
If this doesn't help, post enough information to understand what happens: you the code you posted it is impossinle to see what happens in deletedb function, how unmanaged functions are called.
0
 

Author Comment

by:gvector1
ID: 18104395
Could it be possible that the dll that I am using Interop calls to is not thread safe.  Is it possible that that could have any bearing on this.  I took the first deletedb statement out, but the problem still occurs.  I am thinking that if the dll is not thread safe, when multiple threads are making calls at the same time to the dll that this type of problem can occur.  Is this possible??????
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 18106845
Yes, this is possible. To test this run the same code in one thread and see whether it happens.
0
 

Author Comment

by:gvector1
ID: 18114825
I origionally did this in one thread.  Never had this problem...but it was taking too long.  This application has to transverse hundreds of thousands of directories and parse one specific file in each directory to load it into a database.  Now here is another question.  How can I create a lock that will work across threads.  Basically so when one thread goes to access the dll method call it will lock until it is done and any other subsequent calls will be blocked until the first call is complete.  It that an acceptable workaround and how would it ideally be done?????
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 48

Expert Comment

by:AlexFM
ID: 18115383
You can create static object for synchronization:

static object syncObject = new Object();

Make every call to unmanaged library by the following way:

lock(syncObject)
{
    // unmanaged call
}

Using static synchronization object serializes all calls inside of lock{} block in the whole program.
I don't understand completely your code. Possibly it is enough to protect resources only for every class instance. In this case use non-static synchronization object:
object syncObject = new Object();

Try both versions. First gives better protection, but it is slower. I don't know exactly reading your code, whether you need first or second version.
0
 

Author Comment

by:gvector1
ID: 18115725
My application starts and I start about 30 background workers which work through directories opening specific files that require the dll to read.  Each bg worker opens the file and loads the contents into a database table.  
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 18116594
The criteria is what kind of resources are accessed by function, or unmanaged function. If these resources belong to class instance, it is enough to use protection on instance level. If this is global resource, protection should be done on global (static) level.
0
 

Author Comment

by:gvector1
ID: 18117179
These resources are accessed at an instance level.  Each Background Worker creates an instance of a class that accesses the resource.  So am I correct in saying that if the instance of the class creates a lock on the object, another background worker will not be able to create a lock and access the resource????
0
 
LVL 48

Accepted Solution

by:
AlexFM earned 500 total points
ID: 18120752
This work by the following way. If you make lock on instance level:

lock(syncObject)   // syncObject is non-static
{
    // protected code
}

different threads which try to execute protected code in the same instance, cannot execute it at the same time. Only one thread can enter lock block. If other thread tries to do this, it waits when first thread releases lock, and only after this enters the block. Protected code is always executed only by one thread.

If syncObject is static, only one thread can execute protected code for all class instances.
0
 

Author Comment

by:gvector1
ID: 18229301
Thanks AlexFM,
That lock code helped me out greatly.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Article by: Ivo
C# And Nullable Types Since 2.0 C# has Nullable(T) Generic Structure. The idea behind is to allow value type objects to have null values just like reference types have. This concerns scenarios where not all data sources have values (like a databa…
Introduction Although it is an old technology, serial ports are still being used by many hardware manufacturers. If you develop applications in C#, Microsoft .NET framework has SerialPort class to communicate with the serial ports.  I needed to…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
Concerto provides fully managed cloud services and the expertise to provide an easy and reliable route to the cloud. Our best-in-class solutions help you address the toughest IT challenges, find new efficiencies and deliver the best application expe…

930 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now