Programing

VBA 함수 내에서 개체를 Nothing으로 설정해야합니까?

lottogame 2020. 11. 28. 08:33
반응형

VBA 함수 내에서 개체를 Nothing으로 설정해야합니까?


나는 항상 객체를 다 사용한 후에는 아무것도 설정하지 않는 것이 좋습니다. 그러나 나는 일반적으로 양식 내부의 기능에서만 사용합니다.

객체를 Nothing으로 설정해도 함수 범위가 남아 있으면 참조가 손실되고 메모리가 해제되지 않습니까?

즉 다음을 수행하는 것이 정말 필요합니까?

Set db = Nothing
Set record_set = Nothing

VB는 소위 "참조 계수"가비지 수집기를 사용합니다.

기본적으로 변수가 범위를 벗어나는 순간 참조 된 개체의 참조 카운터가 감소합니다. 개체 참조를 다른 변수에 할당하면 참조 카운터가 증가합니다.

카운터가 0에 도달하면 개체가 가비지 수집 준비가 된 것입니다. 이 문제가 발생하는 즉시 개체 리소스가 해제됩니다. 함수 지역 변수는 참조 횟수가 1보다 높지 않은 개체를 참조 할 가능성이 높으므로 함수가 종료되면 개체 리소스가 해제됩니다.

변수를 Nothing설정하는 것은 참조 카운터를 명시 적으로 줄이는 방법입니다.

예를 들어, 파일을 읽고 호출 Nothing직후에 파일 객체 변수를 설정합니다 ReadAll(). 파일 핸들이 즉시 해제되므로 시간을 들여 내용을 처리 할 수 ​​있습니다.

로 설정하지 않으면 Nothing파일 핸들이 절대적으로 필요한 것보다 오래 열릴 수 있습니다.

"귀중한 리소스 차단을 해제해야합니다"와 같은 상황이 아닌 경우 변수가 범위를 벗어나는 것은 괜찮습니다.


가비지 수집은 거의 완벽하지 않습니다. .NET에서도 가비지 수집을 일찍 수행하도록 시스템에 요청하는 것이 강력히 권장되는 경우가 있습니다.

이러한 이유로, 작업이 끝나면 명시 적으로 닫고 Nothing 레코드 집합으로 설정 합니다.


Microsoft DAO 도움말 및 Access 개발자 참조에서 " Recordset.Close "에 대한 도움말 항목의 맨 마지막 줄은 다음 과 같습니다.

"Close 메서드의 대안은 개체 변수의 값을 Nothing으로 설정하는 것입니다 (Set dbsTemp = Nothing)."

http://msdn.microsoft.com/en-us/library/bb243098.aspx

이를 염두에두고 Microsoft 기술 자료의 "DAO (데이터 액세스 개체)를 사용한 후 데이터베이스 팽창을 방지하는 방법"이라는 제목 의이 기사에서는 데이터베이스가 팽창하지 않도록하려면 명시 적으로 닫아야한다고 설명합니다. 기사가 세부 사항에 대해 약간 모호하다는 것을 알 수 있습니다. "원인"섹션은 거의 횡설수설 할 정도로 명확하지 않습니다.

http://support.microsoft.com/kb/289562

현상 : 데이터 액세스 개체 (DAO)를 구현하여 레코드 집합을 열면 Microsoft Access 데이터베이스가 팽창 (또는 크기가 빠르게 증가)하기 시작했습니다.

원인 : 레코드 세트 코드를 반복 할 때마다 레코드 세트의 메모리를 해제하지 않으면 DAO가 다시 컴파일되어 더 많은 메모리를 사용하고 데이터베이스 크기를 늘릴 수 있습니다.

추가 정보 : 코드에서 Recordset (또는 QueryDef) 개체를 만들 때 완료되면 개체를 명시 적으로 닫습니다. Microsoft Access는 대부분의 상황에서 Recordset 및 QueryDef 개체를 자동으로 닫습니다. 그러나 코드에서 개체를 명시 적으로 닫으면 개체가 열려있는 경우 가끔 발생하는 인스턴스를 피할 수 있습니다.

마지막으로, 15 년 동안 Access 데이터베이스로 작업 해 왔으며 거의 ​​항상 Close 메서드를 명시 적으로 사용하지 않고 로컬로 선언 된 레코드 집합 변수가 범위를 벗어나도록했습니다. 나는 그것에 대해 어떤 테스트도하지 않았지만 그것은 중요하지 않은 것 같습니다.


변수가 범위를 벗어나면 참조를 정리해야합니다. 아마도 이것은 소프트웨어의 이후 버전에서 개선되었지만 한때는 신뢰할 수 없었습니다. 나는 명시 적으로 변수를 "Nothing"으로 설정하는 것이 좋은 습관이라고 생각합니다.


ASP 클래식 (서버 측 스크립팅)을 사용하는 경우 [가상] 서버가 종료 될 때까지 범위를 벗어나지 않기 때문에 모든 개체를 사용할 때 아무것도 설정하지 않도록 가져옵니다.

이러한 이유로 모든 MS VB 스크립팅 예제에서는 항상 개체가 닫히고 아무것도 설정되지 않은 것으로 표시되었습니다. 따라서 스크립트 발췌는 개체가 범위를 벗어나지 않는 ASP 클래식과 같은 환경에서 사용할 수 있습니다.

드물게 개체가 범위를 벗어나지 않는 장기 실행 프로세스를 코딩하고 명시 적으로 개체를 해제하지 않으면 실제 메모리가 부족 해지는 상황이 있습니다.

ASP 클래식을 코딩하거나 다른 이유로 전역 범위에서 프로세스를 실행하는 경우, 예, 명시 적으로 개체를 해제해야합니다.


나는 보통 이것을 내 프로 시저의 끝에 넣거나 모듈 수준의 것을 사용하는 경우 "CloseRecordSet"하위를 호출합니다.

Private Sub Rawr()
On Error GoTo ErrorHandler

    'Procedural Code Here.

    ExitPoint:
        'Closes and Destroys RecordSet Objects.
        If Not Recset Is Nothing Then
            If Recset.State = 1 Then
                Recset.Close
                Conn.Close
            End If
            Set Recset = Nothing
            Set Conn = Nothing
        End If
        Exit Sub

    ErrorHandler:
        'Error Handling / Reporting Here.
        Resume ExitPoint
End Sub

그러나 이렇게하면 절차가 종료되고 (일반적으로 또는 오류로 인해) 개체가 정리되고 리소스가 사용 가능해집니다.

Doing it that way is quite safe in that it you can just slap it in and it will only do what is necessary in regards to closing, or destroying the recordset / connection object, incase it has already been closed (due to a runtime error or just closing it early as ya should, this just makes sure).

Its really not much hassle and its always best to clean up your objects when you're finished with them to free up resources immediately regardless of what happens in the program.


Try this

If Not IsEmpty(vMyVariant) Then
    Erase vMyVariant
    vMyVariant = Empty
End If

참고URL : https://stackoverflow.com/questions/517006/is-there-a-need-to-set-objects-to-nothing-inside-vba-functions

반응형