DLL을 호출할 때 0xc0000005 에러와 함께 LabVIEW가 충돌함

업데이트 됨 Aug 18, 2023

해당 제품

소프트웨어

  • LabVIEW

문의사항

  • DLL을 호출하면 LabVIEW가 충돌하고 메모리 액세스 위반이 발생했다는 에러 메시지가 나타납니다 (Exception Code : 0xc0000005).
  • LabVIEW 버전을 32 비트에서 64 비트로 변경했는데 이제는 Exception Code로 인해 어플리케이션이 임의로 중단됩니다.

해결책

이러한 유형의 충돌을 방지하기 위해 DLL 함수를 호출하는 동안 LabVIEW가 충돌할 수 있는 여러 이유들을 아래를 통해 확인할 수 있습니다.

1. DLL과 동일한 호출 규칙을 사용하고 있는지 확인하십시오
호출 라이브러리 함수 노드의 호출 규칙이 DLL 호출 규칙과 일치하지 않으면 충돌이 발생합니다. 호출 규칙은 아래에 표시된 대로 라이브러리 함수 호출 노드 창의 오른쪽 아래 부분에 지정됩니다.

2. 라이브러리 함수 호출 노드의 모든 입력과 출력을 연결하는지 확인하십시오
라이브러리 함수 호출 노드의 모든 입출력을 연결하지 않으면, DLL 함수는 할당되지 않은 메모리를 덮어 쓰게되고 LabVIEW가 충돌하게 됩니다.

참고 : 두 번째 입력이 첫 번째 입력에 대한 포인터인 경우에 첫 번째 입력에는 출력이 필요하지 않습니다.

3. DLL 함수가 LabVIEW 메모리를 덮어 쓰지 않도록 하십시오.
충분한 메모리가 할당되지 않았거나 DLL 함수가 할당된 것 이상을 쓰면 DLL은 예약된 LabVIEW 메모리 공간을 덮어 쓰게 되고 LabVIEW가 충돌하게 됩니다. DLL에서 배열, 문자열 또는 파형을 전달하고 읽기 전에 메모리가 올바르게 할당되었는지 확인하십시오.

4. LabVIEW가 함수가 예상하는 형식으로 함수에 매개 변수를 전달하는지 확인하십시오
올바르지 않은 매개 변수 데이터 타입 (값, 참조, 핸들 등)을 사용하여 LabVIEW에서 DLL 함수를 호출하면 실수로 잘못된 메모리 위치를 가리키고 데이터가 잘못되거나 LabVIEW 또는 Windows가 손상될 수 있습니다.

5. 함수 호출 자체가 잘못된 무엇가를 합니다.
함수가 잘못된 연산을 시도하면 LabVIEW가 충돌할 수 있습니다. 함수 작성자가 아닌 경우 함수 작성자에게 문의하십시오.

추가 정보

  1. C 호출 규칙을 사용하는 경우 호출자는 스택을 정리해야 합니다. 표준 호출 규칙을 사용할 때 호출된 함수는 스택을 정리합니다. 호출자(LabVIEW)와 호출된 DLL 함수가 동일한 호출 규칙을 사용하지 않으면 스택에서 무언가를 빼내거나 둘 다 수행하지 않습니다. 두 경우 모두 호출된 함수가 반환될 때 LabVIEW가 충돌할 수 있습니다.
  2. 입력을 연결하지 않으면 DLL 함수가 할당되지 않은 메모리를 덮어 씁니다. 출력을 연결하지 않으면, LabVIEW는 DLL 함수가 입력측에 전달된 할당된 메모리를 필요로 하지 않고 다른 것으로 사용한다고 가정합니다.
  3. 많은 DLL 함수는 할당된 메모리를 가져 와서 포인터나 값으로 전달하고 해당 메모리에 쓰고 반환합니다. 메모리가 올바르게 할당되지 않으면 충돌이 발생할 수 있습니다. 예를 들어 다음 함수를 생각해보십시오.

    double *Waveform (double *waveform, uInt32 size);

    이 경우 메모리를 할당하는 적절한 방법은 빈 배열을 전달하는 것이 아닌 size의 매개 변수로 지정된 인덱스를 가진 배열을 초기화하는 것입니다. 아래 이미지는 적절한 방법을 보여줍니다.
LabVIEW에서 DLL을 생성하고 DLL VI의 프런트 패널을 보여주고 싶다면 반드시 따라야 할 두 가지 요구 사항이 있습니다.
  1. DLL 호출이 모든 스레드에서 실행되도록 라이브러리 함수 호출 노드를 설정해야 합니다. 이 설정은 스레드 라디오 단추를 UI 스레드에서 모든 스레드 실행으로 변경하는 것입니다.
참고 : LabVIEW 내장 공유 라이브러리에 대한 모든 호출은 모든 스레드에서 실행으로 지정해야 합니다. LabVIEW 내장 공유 라이브러리를 사용하여 라이브러리 함수 호출 노드를 구성하고 UI 스레드에서 실행을 지정하면 LabVIEW가 멈추고 다시 시작할 수도 있습니다. 자세한 내용은 다음의 링크를 참조 하십시오. : Call Library Function Dialog Box
  1. 호출 VI는 사용자 인터페이스 스레드에서 실행되어서는 안됩니다. 풀다운 메뉴에서 File»VI Properties 를 선택한 후, 항목에서 실행을 선택하면 실행 시스템표준, 인스트루먼트 I/O, 데이터 수집, 기타 1 또는 기타 2 인지 확인할 수 있습니다. 상위 VI가 사용자 인터페이스 스레드에서 실행될 수 있기 때문에 호출자 옵션과 동일하게 선택하지 않아야 합니다.
LabVIEW 7.1 또는 이전 버전에서 다른 프로그래밍 언어로 LabVIEW 코드를 사용하는 방법에 대한 전체 문서는 다음 설명서를 참조하십시오. : Using External code in LabVIEW. LabVIEW 8.0 또는 이후 버전의 더 자세한 정보는 LabVIEW 도움말의 목차에 있는 기본» 섹션을 참조하십시오.

참고 : VI는 다음 단계를 수행하지 않고도 개발 모드에서 계속 실행될 수 있습니다. 그러나 어플리케이션을 만들 때는 위에서 언급한 것처럼 호출 VI를 임의의 스레드에서 실행하도록 설정하십시오.

LabVIEW가 닫힐 때까지 충돌하지 않는 경우
가장 큰 문제는 호출된 DLL 함수가 메모리를 손상시킨 경우입니다. 배열이나 문자열을 DLL에 전달하면 DLL 함수는 배열 크기를 동적으로 조정할 수 없습니다. 배열 또는 문자열의 마지막 요소를 넘어서 쓰기를 하면 메모리가 손상 될 수 있으며 이러한 것들은 LabVIEW가 닫힐 때까지 분명하지 않을 수 있습니다.

에러 검사 - 에러 검사 탭을 사용하여 라이브러리 함수 호출 노드에 대한 에러 확인 레벨을 지정하십시오.

이 탭에는 다음 구성 요소가 포함되어 있습니다.
  • 에러 확인 레벨 - 다음 옵션을 제공합니다 :
    • 최대값 - 라이브러리 함수 호출 노드의 최대 에러 확인 레벨을 사용합니다. 당신이 에러 확인의 최대 레벨을 사용하는 경우에는 기능 탭에서 선택한 호출 규칙이 공유 라이브러리 또는 DLL에서 호출하는 기능의 호출 규칙과 일치하지 않으면 라이브러리 호출 기능 노드에서 에러를 반환합니다. 에러 확인의 최대 레벨은 공유 라이브러리 또는 DLL에서 호출되는 함수가 지정된 문자열 또는 배열 매개 변수에 할당된 공간 이상으로 작성하는 경우에 경고를 반환합니다. 또한 LabVIEW는 에러 확인의 최대 레벨을 통해 호출된 공유 라이브러리 또는 DLL의 실행 중에 발생하는 처리되지 않은 예외로부터 복구할 수 있습니다.
참고 : 에러 확인 탭에서 최대값를 선택하면 실행 속도가 줄어 들고 라이브러리 함수 호출 노드의 메모리 사용이 늘어납니다. 따라서 라이브러리 함수 호출 노드의 구성을 디버깅 할 때만 최대값을 선택해야 합니다.
  • 기본 - 라이브러리 함수 호출 노드에 대한 기본 에러 확인을 사용합니다. 에러 확인의 기본은 LabVIEW가 호출된 공유 라이브러리 또는 DLL의 실행 중에 발생하는 처리되지 않은 예외로부터 복구할 수 있게 합니다.
  • 비활성화 - 라이브러리 함수 호출 노드에 대한 에러 확인을 비활성화합니다. 라이브러리 함수 호출 노드에 대한 에러 확인를 비활성화하면 라이브러리 함수 호출 노드의 실행 속도가 향상됩니다. 그러나 특정 에러로 인해 LabVIEW가 비정상적으로 종료될 수 있습니다. 에러 확인을 사용 불가능하게 하기 전에 라이브러리 함수 호출 노드가 참조하는 함수가 처리되지 않은 예외를 발생시키지 않았는지 확인하십시오.