Solved

Redim of array not always working

Posted on 2014-01-15
6
204 Views
Last Modified: 2014-01-16
I am sending a double-precision array, x(), to the subroutine listed below, and dimensioning ndx() based on the length of x(), which I obtain from x.GetLength(0) - 1.

However, occasionally the loop hangs because ndx() is a shorter length based on use in a previous subroutine.   Therefore, it seems that the Redim ndx(n) statement does not always force the redimensioning to occur.  

When a
  Public Sub processx(ByVal x)
        Dim i As Integer
        Dim n As Integer = x.GetLength(0) - 1

        Array.Clear(arr, 0, UBound(arr))
        Array.Clear(ndx, 0, UBound(ndx))
        ReDim arr(n)
        ReDim ndx(n)
        For i = 1 To n
            arr(i) = x(i)
            ndx(i) = i
        Next

  End Sub

Open in new window

0
Comment
Question by:lep1
  • 3
  • 3
6 Comments
 
LVL 40

Accepted Solution

by:
Jacques Bourgeois (James Burger) earned 500 total points
ID: 39784436
I do not see what causes your problems, but I see a few things that are not what I would expect for this type of code, so maybe changing them might help you.

No need to Clear the array. Redim recreates a brand new empty array unless you call Redim Preserve.

Instead of setting n as GetLength(0)-1, set it to GetUpperBound(0), since redim expects the index to be the UpperBound.

And since arrays are initialized from 0 to UpperBound, why to do you start looping at 1 instead of 0?

Finally, just out of curiosity, what is the use of array ndx? You store 4 in ndx(4) and 25 in ndx(25). No need to ask for ndx(25) if you need the value 25.
0
 

Author Comment

by:lep1
ID: 39784714
arr() and ndx() are sent to an indexed sort routine, where the resulting arr() has sorted x() values (ascending order) and ndx() has the rank of the original values in arr().  Thus, if the original x() was:

x(1)=20
x(2)=5
x(3)=10

returned:

arr(1)=5
arr(2)=10
arr(2)=20

ndx(1)=2
ndx(2)=3
ndx(3)=1
0
 

Author Comment

by:lep1
ID: 39784752
Something I didn't mention was that ndx() is used in a threaded subroutine, and I don't know if use of Redim ndx() in a different non-threaded routine (possibly at the same time) will result in a conflict?

Therefore, if you have

Public array() as Double

in a global declaration module, and then use Redim array(10) in a threaded routine the same time you use Redim array(500) in another non-threaded routine, will there be a conflict over using array() in different routines at the same time?  I think this may be happening.
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 40
ID: 39785357
Yes, you would have a conflict. Variable declared in a module are available everywhere, so changing it in the thread also changes it in the non-threaded routine, that does not expects that change.

That is one of the problems of Public variables in a module. They can simplify a few things, but when you have a problem with them, it can come from anywhere. The problem is made worse when you have a multi-threaded application.

I always tell my students that a global variable is a very rare thing. personally, except for debugging, I might have used only one or two since I started using .NET a dozen of years ago.

There is almost always a way to work with variables that have a more limited scope. This is a better use of resources and help preventing unwanted changes. Almost every time I meet a global variable in somebody else code, it is because the programmer lack of knowledge about things you can do in .NET that were not possible to do in a previous environment.

Old VB6 programmers often design their applications as they did before, and they should not. They use global variables because this is what they did before .NET. They do not know how to pass information between two Windows Forms or are used to a permanent connection to a database and have not learned about the connection pooling that works in the background in ADO.NET.

If you Redim your array in 2 different places at the same time, then it's not the same set of data and should not be the same array. You should prepare your thread so that it uses a copy of the array. Arrays have a CopyTo method that does that.
0
 

Author Comment

by:lep1
ID: 39785474
Got it, so it sounds like a programmer is setting up their code for an impending disaster if you use Public, and then access those memory registers multiple time with different data in the elements and different lengths(?)

You mentioned the CopyTo command, is that a relatively easy way to overcome this issue.

Last, if I have a count variable like

Public Cnt As Integer

and then use Cnt all over the code in instantiated objects (classes) at the same time in loops for example like

Cnt = 0
For i = 1 To n
  If logical = True Then
      Cnt+=1
  EndIf
Next

Something = Cnt


that Cnt could potentially get mangled?
0
 
LVL 40
ID: 39785972
Well, usually, unless you use threads, you cannot be doing 2 things at the same time. So in your loop, Cnt will do what it is intended to do. But maybe, somewhere else, Cnt has a value of 10. It won't have that value anymore after our loop. When you will get back to that somewhere else later, it is expecting 10 but will find something else : bug.

Since you are giving the value of Cnt to Something in your example, why don't you use Something in the loop. I know it's only an example, but you can see there right there, there is a way to work without using a global variable. There is almost always a way.

Public variables in a module (things are different in a class - and think that a Form is a class) are seen everywhere in the application. It very easy to make a change in one place that will have a negative impact somewhere else.

Public variables hold space in memory even when they are not in use.

If you have a bug with a Public variable, it can come anywhere in your 5 modules, 25 forms and 15 classes. Days of fun if you like debugging.

A local variable takes up memory only while it is in use. As far as you are concerned, it is destroyed when you get out of the method. If you have a bug with it, it,s a lot easier to solve, because the variable is used is a lot smaller scope.

Local variables and block variables (a variable declared Inside of a If...End If, a For...Next or any type of code structure that has a beginning and an end is scoped only to that block, a new thing in .NET for VB6 programmers) are always to be privileged.

If you need a local variable in another method, try as much as possible to pass it as a parameter.

This is not always possible however, specially in Forms, where you might need to see a value in 2 events. Since you cannot pass parameters to events, then you need a variable at the Form (class) level.

If you need to use the same variable in 2 forms, create a constructor, a field or a property in the second form, so that the first one can pass the value as a parameter to the second one.

Global variables (Public variables in a module) are to be banned as much as possible.

Unfortunately, a lot of programmers still use them all the time. Sometimes its for a lack of knowledge, because they have learned programming in older languages that have nothing but global variables (the first version of BASIC for instance). Sometimes, its purely because they are lazy. Its easier to do it than to sit and think. They do not like to code but love debugging :-).

Although I do not have the whole picture, the CopyTo seems indeed to be an easy way out of your problem.
Dim ndx1() As Integer

ReDim ndx1(ndx.GetUpperBound(0))	'So that it is the right size to receive the copy
ndx.CopyTo(ndx1, 0)

Open in new window

Use ndx1 in your thread. Since it is a copy, it is completely independant from ndx and changes that you make on one won't break the job that you are doing on the other.
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

IP addresses can be stored in a database in any of several ways.  These ways may vary based on the volume of the data.  I was dealing with quite a large amount of data for user authentication purpose, and needed a way to minimize the storage.   …
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…

708 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

16 Experts available now in Live!

Get 1:1 Help Now