UD_park's IT story
[Error] 처리되지 않은 예외: System.IndexOutOfRangeException 본문
이번에 다룰 오류는 바로
인덱스의 예외 범위를 넘길 때
발생하는 오류 입니다
제가 이 오류가 발생하게된 상황은
크기를 지정하지 않은 문자열 배열을
선언하고, 그 배열에 마음껏
문자열 데이터를 입력해 넣고,
그리고 난 뒤 일정 종료의 신호를 받으면
여태껏 입력 받았었던 문자열 데이터를
저장한 배열로 모두 출력하는
프로그램을 작성중이였습니다
그럼 프로젝트 작성 중이던 소스 코드를
이번 설명의 예제로 사용하여 설명을
시작해보도록 하겠습니다
using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Data.SqlClient; using System.Configuration; namespace ServerSideSocket { class ServerClass { public static Socket Server, Client; public static byte[] getByte = new byte[1024]; public static byte[] setByte = new byte[1024]; public static byte[] dbtmp = new byte[1024]; public static string result = null; public const int sPort = 5000; [STAThread] static void Main(string[] args) { string stringbyte = null; IPAddress serverIP = IPAddress.Parse("192.168.0.8"); IPEndPoint serverEndPoint = new IPEndPoint(serverIP, sPort); try { Server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Server.Bind(serverEndPoint); Server.Listen(10); Console.WriteLine("------------------------"); Console.WriteLine("클라이언트의 연결을 기다립니다. "); Console.WriteLine("------------------------"); //db string connectionString = ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString; using (SqlConnection sqlCon = new SqlConnection()) { sqlCon.ConnectionString = connectionString; // DB에 연결하고, sqlCon.Open(); SqlCommand cmd = new SqlCommand(); cmd.Connection = sqlCon; // dbend Client = Server.Accept(); if (Client.Connected) { while (true) { Client.Receive(getByte, 0, getByte.Length, SocketFlags.None); stringbyte = Encoding.UTF8.GetString(getByte); if (stringbyte != String.Empty) { int getValueLength = 0; getValueLength = byteArrayDefrag(getByte); stringbyte = Encoding.UTF8.GetString(getByte, 0, getValueLength + 1); Console.WriteLine("수신데이터:{0} | 길이:{1}", stringbyte, getValueLength + 1); string stringbyte2; stringbyte2 = Convert.ToString(stringbyte); string commandstr = stringbyte2; cmd.CommandText = commandstr; Console.WriteLine(stringbyte2[0]); if ((stringbyte2[0] == 'I') || (stringbyte2[0] == 'U') || (stringbyte2[0] == 'D')) { Console.WriteLine(stringbyte2); cmd.ExecuteNonQuery(); string sql_select = "SELECT * FROM MemberInfo"; cmd.CommandText = sql_select; SqlDataReader reader2 = cmd.ExecuteReader(); while (reader2.Read()) { string name = reader2.GetString(0); DateTime birth = reader2.GetDateTime(1); string email = reader2.GetString(2); byte family = reader2.GetByte(3); Console.WriteLine("{0}, {1}, {2}, {3}", name, birth, email, family); result = result + name + " " + birth + " " + email + " " + family + "!\n"; } dbtmp = Encoding.UTF8.GetBytes(result); result = null; Client.Send(dbtmp, 0, dbtmp.Length, SocketFlags.None); reader2.Close(); } else if (stringbyte2[0] == 'S') { SqlDataReader reader = cmd.ExecuteReader(); while (reader.Read()) { string name = reader.GetString(0); DateTime birth = reader.GetDateTime(1); string email = reader.GetString(2); byte family = reader.GetByte(3); Console.WriteLine("{0}, {1}, {2}, {3}", name, birth, email, family); result = result + name + " " + birth + " " + email + " " + family + "!\n"; } dbtmp = Encoding.UTF8.GetBytes(result); result = null; Client.Send(dbtmp, 0, dbtmp.Length, SocketFlags.None); reader.Close(); } ///dbend } getByte = new byte[1024]; setByte = new byte[1024]; dbtmp = new byte[1024]; } } } } catch (System.Net.Sockets.SocketException socketEx) { Console.WriteLine("[Error]:@{0}", socketEx.Message); } catch (System.Exception commonEx) { Console.WriteLine("[Error]:!{0}", commonEx.Message); } finally { Server.Close(); Client.Close(); } } public static int byteArrayDefrag(byte[] sData) { int endLength = 0; for (int i = 0; i < sData.Length; i++) { if ((byte)sData[i] != (byte)0) { endLength = i; } } return endLength; } } }
테스트용이라 생각하고 너무 대충
만들었기에 코드가 좀 괴상망측합니다
일단 오류가 발생한 부분은 67번 코드 부터
87번 줄까지의 코드가 없었습니다
풀어서 설명하자면 DB에서는 SELECT문을
쓸때만 read 함수를 사용하는데,
조건문이 SELECT 함수 일때만 동작하다보니
DELETE와 UPDATE, INSERT를 입력하면
while문 안에서 값이 없는 변수그릇을
가공하여 클라이언트로 보내려고 하다보니
에러가 발생한 것이였습니다
위의 예제는 길고 복잡하니
단순하게 제가 일부러 예제코드를 만들어
위와 똑같은 종류의 오류를 발생시키는
소스코드를 보며 설명을 이어가겠습니다
그럼 일단 인덱스 예외 범위를 벗어났다는
오류에 대해서 더 상세히 알아보겠습니다
먼저 오류 구문입니다
처리되지 않은 예외: System.IndexOutOfRangeException: 인덱스가 배열 범위를 벗어났습니다.
이게 도대체 어떤 곳에서 잘못된건지
파악하고 해결하기위해 배열의 사용에
대해서 다시 공부하고 공부했습니다
그래서 얻은 결과는 바로 아래와 같습니다
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1 { class Program { static void Main(string[] args) { string[] arr = { "A", "B", "C"}; for (int i = 0; i <= 4; i++) { Console.WriteLine(arr[i]); } Console.WriteLine("종료"); } } }
위의 예제가 짧고 적당한것 같습니다
arr이라는 문자열 배열은 A, B, C로
3개의 값만 가지고있습니다
그런데 반복문인 for문에서 4까지 돌아간다면
3번째에서 이미 arr의 C가 출력되고
그 뒤는 존재하지않는 값을 출력하려고
컴파일러는 작동하게됩니다
그렇게 된다면 아래와 같은 오류가
발생하게됩니다
즉, 위와 같은 오류가 발생하는 이유는
제대로 선언과 정의를 내리지 않은
변수나 함수 등을 사용하려고 할때
발생하는 오류입니다
이 오류의 해결법은 제 생각에는
오류가 났다고 알려주는 부분의
전부터 그 후까지 천천히 머릿속으로
직접 디버깅하며 어떻게 진행되는지
꼼꼼히 따져보다 보면 말이 되지 않는 부분이
나올겁니다
저 또한 SELECT 문만 받고
DELETE, UPDATE, INSERT문의 경우를
생각하지않고 조건을 걸었기에
위와 같은 오류가 발생하였지만
천천히 연습장과 펜을 들고
손으로 직접 꼼꼼히 디버깅해보니
어디서 오류가 발생하는지 어떻게 고쳐야할지
바로 찾을 수 있게 되었습니다
그럼 이상으로 예외 처리 오류에 대한
포스팅을 여기서 마치도록 하겠습니다
혹시 다른것에 대해 궁금하신게
있으시다면
댓글에 달아주세요
아는것이면 친절하게 쉽게
모르는것이면 또 제가 알아내서
친절하게 쉽게 포스팅해서
설명해드리겠습니다
'IT - For Data > Error' 카테고리의 다른 글
[Error] CS0103 'Process' 이름이 현재 컨텍스트에 없습니다. (3) | 2018.07.13 |
---|---|
[Error] CS1656 '메서드 그룹'인 'Show'에는 할당할 수 없습니다. (0) | 2018.07.12 |
[Error] NullReferenceException (0) | 2018.07.04 |
[Error] CS0103 : 'ConfigurationManager' (2) | 2018.07.04 |
[Error] Error C4996: 'scanf' (0) | 2018.06.28 |