Visual Basic에서는 절차에 인수를 전달하는 두 가지 방법이 있습니다: ByVal(값에 의한 전달, 복사)과 ByRef(참조에 의한 전달, 객체나 변수 자체). 매개변수가 ByRef로 표시되면 절차 내에서 이루어진 모든 변경 사항이 절차 외부의 원래 변수에 반영됩니다.
ByRef를 사용하는 것은 함수에서 여러 결과를 반환하거나 큰 데이터 구조체를 복사하지 않고 작업을 최적화해야 할 때 특히 유용합니다.
예시:
Sub Swap(ByRef a As Integer, ByRef b As Integer) Dim temp As Integer = a a = b b = temp End Sub Dim x As Integer = 10 Dim y As Integer = 20 Swap(x, y) ' x = 20, y = 10
질문: "간단한 데이터 타입(Integer, String)을 다른 스레드 간에 안전하게 참조로 전달할 수 있나요?"
답변: 아닙니다! 스레드 간에 변수들을 참조로 전달할 경우(ByRef), 데이터 경합(data races)이 발생할 수 있습니다. 두 절차가 서로 다른 시간에 변수를 변경할 수 있기 때문에 이는 안전하지 않으며 추적하기 어려운 오류를 초래할 수 있습니다.
예시:
' 멀티스레딩 환경에서는 a와 b의 값이 ' 동시에 접근으로 인해 부정확하게 교체될 수 있는 상황이 발생합니다!
이야기:
오래된 금융 제품에서 여러 모듈 간에 카운터를 전달하기 위해
ByRef를 사용했습니다. 한 개발자가 우연히 변수가 아닌 임시 표현식을 함수에 참조로 전달했습니다. 이것이 프로그램 충돌을 초래했습니다. 왜냐하면 존재하지 않는 참조가 초기화되지 않은 객체를 변경하려고 했기 때문입니다.
이야기:
엔지니어링 계산 시스템이 메모리 절약을 위해 배열을 참조로 전달했습니다. 그러나 누군가 보조 절차 내에서 배열을 변경했습니다. 이로 인해 예상하지 못한 맥락 외부에서 데이터가 변경되면서 추적하기 어려운 버그가 발생했습니다.
이야기:
데이터 분석기에서 성능을 높이기 위해 문자열을 참조로 전달하려고 "최적화"하려 했습니다. 여러 스레드에서 문자열을 참조로 안전하게 전달하지 않아 예측할 수 없는 충돌이 발생하고 동기화 메커니즘이 망가졌습니다.