그동안 미추적으로 쌓여 있던 인수인계 문서를 정리해 올린다. 260903 Door 인터락 현장검증 가이드 / 파워캘 3000W 오적용 환산 260907 Arc 출사 파라미터 시각화 / LaserFrequency 단위계통 / NRE 위험구간 점검 / 레시피화면 사용설명서 260915 레시피화면 작업매뉴얼 260916 PTOP 프로그램 사용설명서 / 자동운전 전환 사전점검 현장용 작업 중 임시본(_backup)은 제외했다.
7.9 KiB
NRE / 크래시 위험 구간 점검
- 작성 : 2026-09-07
- 계기 : 출사 미지원 객체(Ellipse/Rectangle/Roi) NRE 방어(
ISSUE-260907-01) 적용 후, 같은 유형이 더 있는지 전수 확인 요청. - 성격 : 점검 목록 전용. 소스 미수정. 현장 검증 미실시.
- 표기 : 🟩 소스 확인 / 🟦 현장 기록 / 🟨 미확보·판정 불가
점검 범위와 한계
| 구분 | 내용 |
|---|---|
| 포함 | Machines/ILSOS_PrismaticRD_PTOP/**, WeldingComponents/WeldingCommon/Sequences/** |
| 제외 | AuroraVision, LASA GUI(Canvas·DrawTools), AuroraDevices 하위 대부분, Aurora 프레임워크 |
| 방법 | 패턴 검색(FirstOrDefault/First()/[0]/as/인덱서) 후 해당 라인 전후 확인 |
| 한계 | 정적 분석. 런타임 재현·디버깅 없음. 제외 범위에 같은 유형이 더 있을 수 있음 |
0. 선행 확인 — 예외가 실제로 프로그램을 종료시키는가
🟩 우리 소스에 전역 예외 핸들러가 없습니다.
DispatcherUnhandledException / AppDomain.CurrentDomain.UnhandledException /
UnobservedTaskException / SetUnhandledExceptionMode 검색 결과 0건.
🟩 ILSOS_PrismaticRD_PTOP.csproj → OutputType=library.
즉 실행 주체는 Aurora.exe 이고 저장소에 소스가 없습니다.
🟨 따라서 아래 항목이 실제로 프로세스를 종료시키는지는 판정할 수 없습니다.
- Aurora.exe 가 전역 핸들러를 걸어 두었는지 미확인
- Aurora
SequenceBuilder가 노드 실행을 try/catch 로 감싸는지 미확인 (sb.OnForceError(...)훅이 존재하므로 잡을 가능성은 있음)
이 문서는 "NRE 가 발생할 수 있는 지점" 목록입니다. "여기서 프로그램이 죽는다" 로 읽지 마십시오. 종료 여부는 별도 확인 필요.
A. 널 체크 없이 즉시 역참조 — 위험도 최상
A-1. SeqComponentTeachingRun.cs:456-459 🟩
var power = Status.GetProcessingWeldingData().UploadProcessDatas
.Where(data => data.DataName == $"Power_{SlotNo}_{_SequenceSetting.LastPageNo}")
.FirstOrDefault();
power.Value = ScannerCanvasUserCtrl.ScannerParams[paramIndex].LaserPower1
+ ScannerCanvasUserCtrl.ScannerParams[paramIndex].LaserPower2; // ← power == null 이면 NRE
var velocity = ...Where(data => data.DataName == $"Velocity_{SlotNo}_{...}").FirstOrDefault();
velocity.Value = ScannerCanvasUserCtrl.ScannerParams[paramIndex].MarkSpeed; // ← 동일
DataName을SlotNo+LastPageNo로 문자열 조합해 찾습니다.- 그 조합이
UploadProcessDatas에 없으면FirstOrDefault()가null을 반환합니다. - 페이지 수가 늘거나 슬롯 번호 체계가 바뀌면 즉시 발생합니다.
- 실제 운전 경로(Manual 티칭런)라 재현 가능성이 목록 중 가장 높습니다.
A-2. SeqEventQTest.cs:142-145 🟩 — 3중 위험
FovInfo _fovInfo = VisionRecipeManager.GetFovInfos().FirstOrDefault();
_PatternAgent = FovPatternAgentManager.GetAgent(_fovInfo.ToSubSysInfo()); // ① _fovInfo null → NRE
List<PatternInfo> patterns = _PatternAgent.GetMainPatterns(_fovInfo); // ② agent null → NRE
_PatternInfo = patterns[0]; // ③ 빈 리스트 → IndexOutOfRange
A-3. SeqAutoRunPrismatic.cs:1101-1104 🟩
A-2 와 동일 패턴 + _Patterns[_InitParam.VisionRecipeNo] 인덱스 무검증.
🟩 참고 — 올바른 패턴이 같은 파일에 이미 있습니다.
SeqAutoRunPrismatic.cs:743-745는_PatternResult?.Results?.FirstOrDefault()로 널 조건 연산자를 쓰고 이후if (baseResult != null)까지 확인합니다. A-2 · A-3 만 이 방어가 빠져 있습니다.
B. as 캐스팅 결과를 가드 없이 보관 — 지연 발화형
캐스팅 실패 또는 키 부재 시 조용히 null 이 되고, 한참 뒤 그 필드를 사용하는 시점에 터집니다.
발생 위치와 원인 위치가 달라 추적이 어렵습니다.
| 위치 | 대상 | 🟩 |
|---|---|---|
SeqAutoRunPTOP.cs:291 |
_SystemParameter |
🟩 |
Views/Main/UCMainAutoRunViewModel.cs:95-97 |
_SystemParameter, _Scanner, _Plc |
🟩 |
Views/Main/UCMainAutoRunViewModel.cs:472, 505 |
_SystemParameter 재대입 |
🟩 |
SeqTestRun.cs:472 |
_IOLaser |
🟩 |
SeqComponentTeachingRun.cs:179 |
_SequenceSetting |
🟩 |
Monitoring/SeqStatusMonitor.cs:60 |
_SequenceSetting |
🟩 |
SeqAutoRunPrismatic.cs:1050 |
SystemSetting |
🟩 |
EquipmentSetup.cs:90, 199, 240, 342 |
EquipmentInfo |
🟩 |
EquipmentSetup.cs:129, 133 |
IODevice, PLCControllerPTOP |
🟩 |
Recipes/RMSHandlerForPTOP.cs:52-53 |
_plc, _RmsSetting |
🟩 |
대부분 초기화 구간이라 정상 구성에서는 성공합니다. 위험은 "설정 키 이름 변경 / 디바이스 등록 누락 / 타입 교체" 시 즉시 실패하지 않는다는 점입니다.
🟩 예외 — 이미 방어된 곳 : SeqAutoRunPTOP.cs:1140, 1252 의 LaserInterlockSetting 은
LaserAngleOffsetSelector.Select() 안에서 setting != null 삼항 처리로 방어됩니다.
C. 인덱스 무검증 — NRE 는 아니나 동일하게 종료 요인
| 위치 | 위험 | 🟩 |
|---|---|---|
SeqUploadWeldingList.cs:206 |
SelectedDrawObjectList[0] — 빈 리스트 |
🟩 |
SeqUploadWeldingList.cs:207-209 |
ScannerParams[ScannerParamID - 1] — ID 가 0 이면 인덱스 -1 |
🟩 |
SeqUploadWeldingList.cs:474, 617-631, 719, 1006, 1052, 1152, 1204, 1404, 1605 |
ScannerParams[obj.ScannerParamNo] 범위 무검증 (배열은 128개 고정 생성) |
🟩 |
SeqWaitWeldOrChangePage.cs:194-195 |
ScannerParams[paramIndex] |
🟩 |
SeqTestRun.cs:237-238 |
ScannerParams[paramIndex] |
🟩 |
SeqComponentTeachingRun.cs:457-465 |
ScannerParams[paramIndex] |
🟩 |
SeqAutoRunPrismatic.cs:1104 |
_Patterns[VisionRecipeNo] |
🟩 |
SeqUploadWeldingList.cs:206-209 주의 — 2026-09-07 적용한 예외처리는
FuncLoadDrawObjectScannerParamSelected() 쪽이라 이 경로는 여전히 무방비입니다.
D. 예외는 안 나지만 값이 오염되는 것 (참고)
double 나눗셈이라 예외 대신 Infinity/NaN 이 조용히 흘러갑니다.
| 위치 | 내용 |
|---|---|
ScannerRTC6.cs:775 · ScannerRTC5.cs:773 |
32.0 / periodHz — periodHz == 0 이면 Infinity → (uint) 캐스팅은 정의되지 않은 동작 |
SeqUploadWeldingList.cs:1313-1316 |
ArcRampingInterval == 0 시 동일 |
상세 : 260907_LaserFrequency_단위계통_분석.md
우선순위 제안
| 순위 | 항목 | 근거 |
|---|---|---|
| 1 | A-1 | 실제 운전 경로(Manual 티칭런) + 조합 문자열 탐색이라 재현 가능성 최상 |
| 2 | C 의 SeqUploadWeldingList.cs:206-209 |
이번 예외처리가 커버하지 못한 인접 경로 |
| 3 | A-2 / A-3 | 비전 경로. Vision 미사용이면 후순위 |
| 4 | B | 개별 수정보다 초기화 구간 일괄 널 가드 + 알람이 적절 |
| — | 선행 | Aurora.exe / SequenceBuilder 의 예외 처리 정책 확인. 이게 정해져야 "가드 후 어떻게 할지"(스킵 / 알람 / 시퀀스 중단)가 결정됨 |
조치 시 주의
- 조용히 스킵하면 안 되는 경우가 있습니다. A-1 은 공정 데이터 상신 실패를 뜻하므로, 널이면 로그만 남기고 넘어가면 데이터 누락이 은폐됩니다. 알람 여부를 함께 정해야 합니다.
- 반대로 이번
ISSUE-260907-01처럼 원래도 동작하지 않던 경로는 스킵이 맞습니다. - 즉 "널이면 무조건 return" 을 일괄 적용하지 마십시오. 항목마다 판단이 다릅니다.
변경 이력
| 일자 | 내용 | 비고 |
|---|---|---|
| 2026-09-07 | 최초 작성. PTOP + WeldingCommon Sequences 범위 점검 | 소스 미수정 |