Index out of bounds, but index is actually within bounds C# [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 months ago.
Improve this question
My C# (unity) application claims that an index I am trying to access within an array of strings is out of the bounds of the array. It is not. Here is the array:
public string[] fen =
{
"2q3k1/8/8/5N2/6P1/7K/8/8 w",
"7k/8/8/4b1n1/8/8/5PPP/5R1K w",
"r1bqkb1r/pppp1ppp/2n5/4p3/2B1N3/5N2/PPPP1PPP/R1BQK2R b"
Here is the code accessing it:
void Update()
{
if (PuzzleVariables.instance.puzzlePassed)
{
if (PuzzleVariables.instance.fen.Length < PuzzleVariables.instance.puzzlenumber + 1)
{
SceneManager.LoadScene("ModuleCompleted");
}
else
{
PuzzleVariables.instance.puzzlePassed = false;
FENbuild(PuzzleVariables.instance.fen[PuzzleVariables.instance.puzzlenumber -1]);
}
}
}
Instead of moving on to the next puzzle, it goes on to the ModulePassed screen.
Whenever I try printing the length of this array, it reads 1. What am I doing wrong here?

First
When the runtime says that you are out of bounds, then you ARE out of bounds.
There is no point in arguing that you are not out of bounds with the runtime. Empirically, almost everytime people discuss with their compiler, (ignoring the fact that the compiler is a bad discussion partner because it will not talk back to you but stubbornly repeat his argument over and over, and is not convincable, and immune to threats of all sorts, like throwing pc out of the window and such), it turns out: compiler is right, you are wrong. So skip that episode, and search for the mistake you made instead.
Second
If Puzzlenumber is anything other than 1, 2, or 3, or the Array is shorter than that (non initialized, using wrong array, etc), this will crash. Place a breakpoint on the line where you access your array, and check your variable and also check PuzzleVariables.instance.fen.Length. You might have initialized something you dont use.
Third
Stacktrace. Check your stacktrace to see if your line crashes, or the crash is WITHIN the method FENbuild. Maybe your input is working, but causes a crash down there.
Fourth
Singletons are only used when there is a technical reason for a class to have only one instance, (i.e. resource, printer, etc.).
Is there a reason why you do not work with normal instances? If not, singleton is an Antipattern.
Is say this, because singletons, can have side effects that also make your thing crash. Especially in a multithreaded environment like unity is.
Fifth
In Unity Inspector a public string[] fen; might be serialized => it can have totally different content assigned in the inspector, be empty etc. Changing the code afterwards doesn't change the already serialized array => The Inspector overrules any later changes in code unless you Reset the component
In short:
Please post stacktrace and maybe some reproducable code, and never use singletons.

Related

Can't figure out how this method produces garbage and how to fix it

I've got a method that I'm calling ... well, very often. And now the GC is becoming a problem, because apparently this method is creating garbage, but I can't seem to figure out why.
Item item;
foreach (Point3D p in Point3D.AllDirections)
{
item = grid[gridPosition + p];
if (item != null && item.State != State.Initialized)
else
return;
}
OtherMethod(this);
This method is inside the Item class and figures out the state of neighbouring items. The gridPosition variable is obviously the position of this item inside the grid and the Point3D is a struct that just contains 3 ints, one for each axis. It also contains a few predefined static arrays such as AllDirections which itself only contains Point3Ds.
Now, the state of items can change at any time and once all neighbours have a specific state (or rather aren't in the Initialized state) I do some other stuff (OtherMethod), which also changes the state of the item so this method is no longer called. As such the produced garbage is only a problem when neighbours don't change their state (for example when there is no user input). I guess you could think of this as a substitution for an event driven system.
I admit that I have a rather limited understanding of memory management and I tend to only really understand things by doing them, so reading up on it didn't really help me much with this problem. However, after reading about it I got the impression that every value type, that is defined within a method and doesn't leave it, will be collected upon leaving the method. So I have a little trouble figureing out what's actually left after the return.
Any ideas on what's actually generating the garbage here ? Of course the best case would be to produce no garbage at all, if at all possible.
(Just in case this is relevant, I'm working in Unity and the method in question is the Monobehaviour Update)
Edit for all the comments:
Holy cow you guys are quick. So...
# Jeppe Stig Nielsen: There is nothing between if and else, there was once but I didn't need that anymore. It's just a quick way to leave if no neighbour was found. Also, Indexer ! Completely forgot about that, here it is:
public Item this[Point3D gridPosition]
{
get
{
Item item;
items.TryGetValue(gridPosition, out item);
return item;
}
}
Could the TryGetValue be the reason ?
# Luaan: I already tried a normal for loop, didn't change anything. That looked something like this:
for (int i = 0; i < 6; i++)
{
item = grid[gridPosition + Point3D.AllDirections[i]];
}
If it was the enumerator, that should've fixed it, no ?
# Rufus: Yes that's a better way to write the if, will fix that. The whole thing is a work in progress right now, so that's just a remnant of past experimentation. There is currently is nothing else in the if statement.
# Tom Jonckheere: Well there isn't really much else. It's just Unitys Update() followed by two if statements for the State. And that's really just because I currently only work with two states but have already setup more, so someday there will probably be a switch instead of ifs.
# Adam Houldsworth: Well yes, the problem is certainly that I call it so often. The odd thing is, the amount of garbage produced varies wildly. As far as I can tell it's in the range of 28 bytes to 1.8KB. As for the whole red herring thing, I don't think that's the case. The profiler points to the Update method, which only contains two ifs, one which is the code from above, the other one isn't being used when no state changes occur. And when testing, there are no state changes, except for intial setup.
Also, sorry for the wrong tag, first time I've visited this site. Looks like I'll have some reading to do :)
foreach calls GetEnumerator, which, in turn, creates a new instance of Enumerator every time it's called.
So after Jeppe Stig Nielsen and Luaan made me remember that I'm infact using an indexer I did some googleing and found out that this is not a new issue. Apparently Dictonary.TryGetValue works by calling Equals(object o) on the keys. Now these have to be unboxed which, as far as I understand it, creates the garbage. I now followed the advice I found on Google and implemented the IEquatable interface in my Point3D struct, which does not requiere any boxing. And as it turns out, a big chunk of the garbage is gone.
So the generated garbage per call went from ~28B-1.8KB down to ~28B-168B. Which is pretty good, no more GC spikes. Though I'm still curious where the rest of the garbage is coming from.
Anyway, this was already a big help, so thanks for your answers guys.
Edit: Figured out where the rest of the garbage was comeing from. I just called base.GetHashCode, because I didn't know any better. I did some research into pretty much everything related to hash codes and then implemented it correctly. And now I'm down to exactly 0 bytes of garbage. Pretty neat.

Where should I put my try and catch in my game? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm building a Number Guessing Game for a lab in school, the basic rules of the game are you have 10 guesses to try to guess the number between 1 and 100. My teacher want me to put all the game logic in one class and use the btn_Click methods in the form class to call methods from the game logic class. I feel like it makes sense to put the try catch in the btn_CLick methods because then I can use MessageBox.show to put a message like "You have to enter a number" or "Then number must be between 1 and 100" and but he said he wants the me to be able to take the code and use it without the form class. Any suggestions?
I would not use a try-catch. You could use a TryParse and convert your input from a string into an integer. If it doesn't convert just show an error. If it does convert to an integer you can do an if-then to find out if it's within your wanted parameters.
This could be done via methods contained in the "Logic Class". You could have one method return a true/false that checks if the input is able to be an integer and another that can determine if it's in the range you want.
Your UI would then take those true/falses and display/not display your message box for an error message.
Try/Catches are expensive and it's not useful in this case. If/thens and input validation/sanitation would solve the problems you could have for this program.
I would suggest not using try/catch at all unless you really really need it. So for validating user input, instead of attempting to type-cast the value, which may throw an exception, inspect the input string to see if it is an integer. I'd be surprised if there wasn't already a method for doing this in the C# Library.
Your game logic should be unconcerned with the where and how you get the guesses (numbers) so there really shouldn't be any need for try/catch in the game logic. I'd imagine it would expose a method that might look like this:
public GuessResult MakeAGuess(int guess)
Notice that it takes an integer which it's going to compare with the target number. So nothing here is going to throw. The body might look something like this:
public GuessResult MakeAGuess(int guess)
{
if (guess > target)
return GuessResult.TooHigh;
if (guess < target)
return GuessResult.TooLow;
return GuessResult.Correct;
}
Where GuessResult is a public enum with TooHigh, TooLow and Correct values.
Your UI will be responsible for converting strings to numbers (if that's needed) and any try/catching would be done there. BUT, it would be better to use int.TryParse rather than int.Parse wrapped in a try/catch because it is more efficient. Even better would be to use a more appropriate control on your form to get user input. One that actually is designed for numbers.

"Source array was not long enough" Error registering BsonClassMap conventions in mongodb with C# driver

In the following code:
var myConventions = new ConventionProfile();
myConventions.SetIgnoreExtraElementsConvention(new AlwaysIgnoreExtraElementsConvention());
BsonClassMap.RegisterConventions(myConventions, (type) => true);
whenever it calls RegisterConventions, we are getting the following error, but it is very intermittent and random, and so it's very hard to troubleshoot.
"Source array was not long enough. Check srcIndex and length, and the
array's lower bounds."
A few times we've purged our collections and that's fixed it, but the last few times, we purged and still had to then restart the windows service. Then we could use our application and create records and collections to our hearts' content.
I'm thinking perhaps an array in one or more of our mapped class's array properties is getting initialized inconsistently, but I'm drawing a blank on next steps to take. I could perhaps use a field initializer or initialize it in the constructor, but I don't want to start mucking with mongo api's mapping magic. Also, we haven't seen this error in at least a week, so if I made some sort of fix and left it in there, I'll have no way of knowing if it actually fixed the problem or not.
Please help! Thanks!

Can a String[] hold System.Object inside it?

Do you feel question is strange? yes what happened also strange. let me explain.
I have found a snippet from this Covariance and Contravariance with C# Arrays
string[] strings = new string[1];
object[] objects = strings;
objects[0] = new object();
Jon skeet explains that above code will throw ArrayTypeMismatchException, as said yes it does.
what I did is I put a breakpoint in line 3, Using DebuggerVisualizer I manually set objects[0] = new object() it doesn't throw any error and it works. later checking strings[0].GetType() returns System.Object. not only System.Object any type can be set in string[] by above mentioned procedure.
I have no idea how this happened i raised my question as a comment over there in the very same question i saw this but no answers.
Am curious to know what is happening behind. Anybody explain pls.
Edit1 This is even Interesting
After reproducing the above behaviour try this
int len = strings[0].Length;
if you place mouse over the Property Length is says strings[0].Length threw ArgumentException with message Cannot find the method on the object instance but actually it doesnt throw exception and code runs yielding result len=0
Your example seems to answer the question: yes, a string reference can refer a non-string object. This is not intended, however.
Consider what you have found, a bug in the debugger.
As Jon Skeet explains in the answer you mention, because .NET arrays have this "crazy" covaraiance even though arrays are not read-only but more like read-write, everytime one writes to an array of references the framework has to check the type of the object one tries to write to the array, and throw an ArrayTypeMismatchException if you're about to use a wrong type, like assigning an instance of Cat to an array of Dogs (a runtime Dog[]) which has been cast by "crazy" covariance into an Animal[].
What you have demonstrated is that when we use the Immediate window of the Visual Studio debugger (or similar windows), this required type check is not done, and as a result this can lead to any type Y (except pointer types probably) being assigned to a reference type variable of any reference type X. Like this:
X[] arrayOfX = new X[1];
object[] arrayCastByCrazyCovariance = arrayOfX;
Y badObject = new Y(); // or another constructor or method to get a Y
// Set breakpoint here.
// In Immediate window assign: arrayCastByCrazyCovariance[0] = badObject
// Detach debugger again.
X anomalousReferenceVariable = arrayOfX[0];
anomalousReferenceVariable.MemberOfX(); // or other bad things
This can make a Cat bark like a Dog, and stuff like that.
In the linked thread on Bypassing type safeguards, the answer by CodesInChaos shows an unrelated technique with which you can put a reference to an object of a "wrong" and unrelated type into a reference variable.
(I have preferred to rewrite my answer because the previous one had too many updates and wasn't clear enough).
Apparently, it has been found a not-so-perfect behaviour in one of the tools (Immediate Window) in the VS debugging part. This behaviour does not affect (AT ALL) the normal execution of the code and, purely speaking, does not affect even the debugging process.
What I meant in the last sentence above is that, when I debug code, I never use the Immediate Window, just write any code I want, execute it and see what the debugger shows. The referred problem does not affect this process (which can be called "debugging actually-executed code"; in the proposed example, pressing F11 when you are on objects[0] = new object();), what would imply a serious problem in VS. Thus from my point of view (the kind of debugging I do) and from the execution point of view, the referred error has no effect at all.
The only application of this error is when executing the "Immediate Window" functionality, a feature of the debugger which estimates what the code will deliver before it actually delivers it (what might be called "debugging not-executed code" or "estimating expected outputs from non-executed code", etc.; in the proposed example, being on line objects[0] = new object();, not pressing F11 but using the Immediate Window to input values and let this feature to tell you what is expected to happen).
In summary, the referred problem has to be understood within the right context, that is, it is not an overall-applicable problem, not even a problem in the whole debugger (when you press F11 in the referred line from the debugger, it outputs an error and thus the debugger does understand perfectly that this situation is wrong), but just in one of its tools. I am not even sure if this behaviour is even acceptable for this tool (i.e., what "Immediate Window" delivers is a prediction which might not be 100% right; if you want to know for sure what will happen, execute the code and let the debugger show you the information).
QUESTION: Can a String[] hold System.Object inside it?
ANSWER: NO.
CLARIFICATION: covariance is a complex reality which might not be perfectly accounted by some of the secondary tools in VS (e.g.,
"Immediate Window") and thus there might be cases where the
aforementioned statement does not fully apply. BUT this is a local
behaviour/bug in the specific tool with no effect in the actual
execution of the code.

What could be causing an NRE when closing a form?

Under certain circumstances, I get an NRE when closing a form using its Close button, which simply calls the native (WinForms) Close() method.
Certain paths through the code do fine, but one particular path causes the Null Reference Exception. Since this is nominally a scenario where something that is null is being referenced, how could this be taking place when the form is simply being closed? I can imagine there being a memory leak, perhaps, but something null being referenced I'm not understanding.
What potential causes in the code might there be?
UPDATE
Answer to Jon Skeet:
I'm unable to debug this in the normal way for reasons boring and laborious to relate (again), but what I can do is this:
catch (Exception ex)
{
MessageBox.Show(ex.Message);
MessageBox.Show(ex.InnerException.ToString());
SSCS.ExceptionHandler(ex, "frmEntry.saveDSD");
}
The last is an internal/custom exception processing method.
All I get from these lines is:
"Null Reference Exception"
Nothing (empty string)
"Exception: NullReferenceException Location: frmEntry.btnSave.click
Note that the last exception shown now implicates btnSave.click as the culprit, whereas it formerly pointed the finger at saveDSD. Curiouser and curiouser. Is this a case of the Hawthorne Effect* in action (well, a modified Hawthorne Effect, in the sense that adding this debugging code might be changing things).
The canonical Hawthorne Effect being more like this sort of scenario: A bunch of cats are playing basketball. Some girls walk up and watch. The cats start showing off and hotdogging, and one breaks his leg. Is it the girls' fault? No. Would it have happened had they not been watching? No.
UPDATE 2
Talk about the Hawthorne Effect: When I copied the two MessageBox.Show() calls to the catch block of frmEntry.btnSave.click, I then got:
"Null Reference Exception"
"Null Reference Exception"
"Exception: NullReferenceException Location: frmEntry.Closing"
IOW, the location of the NRE keeps moving about, like a squirrel on a country road when [h,sh]e meets two cars going opposite directions.
UPDATE 3
And it happened once more: adding those MessageBox.Show()s to the form's Closing event causes the NRE to pop up out of a different hole and declare itself. This inbred code is begetting (or cloning) half-wits by the score, or so it seems.
UPDATE 4
If writing bad code were a crime, the cat who wrote this stuff should be in solitary confinement in a SuperMax.
Here's the latest egregious headscratcher/howler:
int cancelled = ListRecords.cancelled;
if (cancelled == 0)
. . .
The public "cancelled" member of ListRecords (in another class) is only ever assigned values of 0 and 1. Thus, not only does cancelled sound like a bool, it acts like a bool, too. Why was it not declared as a bool?!?!?
The official image of this codebase should be Edvard Munch's "The Scream"
UPDATE 5
Maybe I'm venting, but recent experiences have caused me to come up with a new name for certain types of code, and an illustration for many projects. Code that doesn't go anywhere, but simply takes up space (assignments made, but are then not acted on, or empty methods/handlers called) I now call "Winchester Mystery House code."
And for the typical project (I've been a "captured" employee as well as a contractor on many projects now, having almost 20 years experience in programming), I now liken the situation to a group of people wallowing in quicksand. When they hire new people to "come aboard," they really want them to jump into the quicksand with them. How is this going to help matters? Is it just a case of "misery loves company"? What they should be doing is saying "Throw us a rope!" not "Come on in, the quicksand is fine!"
Many times it's probably just entropy and "job security" at play; if they keep wrestling with the monstrosity they've chosen or created, their hard-won knowledge in how to keep the beast more-or-less at bay will keep them in their semi-comfy job. If they make any radical changes (most teams do need to make some radical improvements, IMO), this may endanger their employment status. Maybe the answer is to employ/contract "transition teams" to move teams/companies from prehistoric dinosaur-clubbing times into the 21st Century, training the "old guard" so that they can preserve their jobs. After all, there aren't enough of these "saviors" to steal the old hands' jobs anyway - train them up, get them up to speed, and move on. All would benefit. But many seemingly prefer to continue wallowing in the mire, or quicksand.
Before anybody hires a programmer, they should give them at the minimum a test wherein passing the test would prove that they are at least familiar with the basic tenets delineated in Steve McConnell's "Code Complete."
Okay, back to battling the quicksand...
UPDATE 6
Or: "Refactoring Spo-dee-o-dee":
A "gotcha" with refactoring is if you change the name of a variable such as this:
ChangeListType chgLst; // ChangeListType is an enum
...to this:
ChangeListType changeListType;
...and if there is a data table with a column named "chgLst", SQL statements can also get changed, which can ruin, if not your day, at least part of it.
Another potential gotcha is when you get, "[var name] is only assigned but its value is never used" hints. You may think you can just cavalierly 86 all of these, but beware that any related code which you may comment out along with assignments to these dead vars is not producing relied-upon side effects. Admittedly, this would be a bad way to code (side effectual methods storing their return vals in vars that are ignored), but ... it happens, especially when the original coder was a propeller-head mad scientist cowboy.
This code is so chock full of anti-patterns that I wouldn't be surprised if Butterick and/or Simplicity put out a contract on this guy.
On second thought, aside from the architecture, design, coding, and formatting of this project, it's not really all that bad...
Mary Shelley's "Frankenstein" was very prescient indeed, but not in the way most people have thought. Rather than a general foreboding about technology run amok, it is much more specific than that: it is a foregleam of most modern software projects, where "pieces parts" from here and there are jammed together willy-nilly with little regard to whether "the hip bone's connected to the thigh bone" (or should be) and whether those parts match up or will reject one another; the left hand doesn't know what the right is doing, and devil take the hindmost! Etc.
That can happen under any of these situations:
object obj is null and your code has obj.ToString()
string item is null and your code has item.Trim()
Settings mySettings is null and your code has mySettings.Path
Less common things would be a thread running that posts information or a serial port that tries to receive data after the SerialDataReceivedEventHandler has been removed.
Look at what your suspect form's code and the parent form's code are doing about the time this suspect form is closed and what other processes might be running on the suspect form.

Categories