Solved

Protected Memory Exception

Posted on 2006-12-01
12
258 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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
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

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

758 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

18 Experts available now in Live!

Get 1:1 Help Now