2013-04-10 1 views
0

EDIT : 콜백 템플릿에 backquotes가 추가되었습니다. 인터페이스는 별표가 아닌 markdown 표시기로 별표를 읽는 중이었습니다!C++ 누락 된 콜백 함수 테스트

필자는 Windows DLL/Linux에서 콜백 함수를 등록하는 방법을 사용자 응용 프로그램에 제공합니다. 훌륭하게 작동합니다. 콜백 프로토 타입은 다음과 같습니다. (void)(*callback)(void*);

문서를 작성하는 동안 편집증에 시달렸으며 등록 된 주소가 유효한지 알 수있는 방법이 없습니다. 유일한 피드백은 크래시이거나 콜백을 try/catch 내부에서 호출하는 것입니다.

콜백이 존재하지 않고 누가 실행되는지 - 어떤 예외가 발생할지 전혀 알지 못합니다. "아무데도"호출이 충돌 대신 예외를 생성 할 정도로 충분히 복구 될 수 있다고 확신 할 수도 있습니다.

예, 사용자의 문제입니다. 사려 깊고 사용자가 자신의 버그를 이해하는 데 도움이 될 수 있습니다.

그럼 예외는 무엇입니까? Windows와 Linux가 서로 다른지 확인하십시오.

누락 된 기능을 감지하기 위해 예외 포착을 사용하지 않고도 더 잘 접근 할 수 있습니까?

+2

NULL을 테스트하고 callback! = NULL 인 경우 함수를 호출 할 수 있습니다. 유효성에 대한 콜백 주소를 테스트하거나 잘못된 주소 호출 후에 복구 할 수있는 신뢰할 수있는 휴대용 방법은 없습니다. –

+0

공유 라이브러리에서 콜백 함수를 호출하려는 경우 유일하게 테스트 할 수있는 콜백 포인터를 null과 비교하는 것입니다. =) 더 좋은 방법은 없습니다. 프로그램에서 segfault를 얻으면 복구 할 수 없습니다. 현재 응용 프로그램을 손상시키지 않고 extern 코드를 실행하는 유일한 방법은 프로세스를 포크하고 거기에서 뭔가를 실행하여 어떤 일이 발생하는지 확인하고 분기 된 프로세스에서 데이터를 가져 오는 것입니다. 그러나 a) 사용자는 프로세스가 포크를 할 것으로 기대하지 않습니다. b) 그가 이것을 원한다고해도 콜백 전에는 공유 할 수없는 모든 리소스를 닫아야합니다. 일반적으로 불가능합니다. – JustAnotherCurious

+0

@JustAnotherCurious 사실, 별도의 스레드가 아닌 별도의 프로세스에서 플러그인을 실행하면 더 많은 또는 덜 표준적인 프로 시저가 현재 지원됩니다. 거의 모든 브라우저가이를 수행합니다. –

답변

5

복구 할 방법이 없습니다. 마찬가지로 콜백에 *(int*)(0x1234) = 5;과 같은 행이 포함되어 있으면 복구 할 수 없습니다. 그냥 그걸로 살아라.

C++ 라이브러리 개발자는 아무 것도 충돌하지 않도록하기 위해 비즈니스를 수행하지 않습니다. 문서 작성 방식을 사용할 때 약속 한대로 코드를 제공하기 만하면됩니다.

0

은 여기 대답으로 : 포인터가 "하지 인식 NULL 또는 이와 유사한"이면

How to test if an instance is corrupted?

을 (완전히 다른 질문의 유형, 그러나 동일 적용), 다음 코드에서 방법이 없습니다 그것이 유효한지 아닌지 알기 위해

"코드 실행 실패"가 throw되지 않기 때문에 try/catch을 사용하여 실패를 포착 할 수도 없습니다.

"프로그래머 오류"이래로, 나는 큰 문제라고 생각하지 않습니다. 프로그래머는 어쨌든 자신의 코드로 원하는대로 할 수 있습니다. 따라서 어떤 메커니즘을 추가하든간에 어떤 방식 으로든 우회 할 수 있습니다.

+1

"바보들이 독창적이기 때문에 아무 것도 만들 수 없습니다." 머피의 법 _ 1970 년 중반부터 케이트에 언젠가부터. –

+0

실제로. 만약 당신이 그것을 더 확실하게 만들면, 누군가는 단지 더 나은 바보를 내놓을 것입니다 ... –

2

주제가 약간이지만 0 123 인수를 취하는 void(*)() 형태의 콜백이 유용하지 않습니다. 유용한 C 스타일 콜백은 사용자가 콜백에 해당하는 상태를 찾을 수 있도록 사용자가 지정한 인수를 허용합니다. 예컨대 :

typedef void callback_fn(void* user_arg); 

callback_id register_callback(callback_fn* callback, void* user_arg); 
void unregister_callback(callback_id); 

user_arg없이 콜백의 사용자는 콜백 함수에 해당하는 상태를 저장하는 글로벌 변수를 사용하도록 강요됩니다.

+0

+1보다 더 조심 스럽기 때문에 +1. 콜백 템플릿에 역 따옴표를 추가했습니다. 인터페이스는 별표가 아닌 markdown 표시기로 별표를 읽는 중이었습니다! 템플릿은 실제로'(void) (* callback) (void *)'였습니다. –

1

당신이 묘사하는 상황은 가능성이 희박합니다. 나는 그런 취급을 어디에도 보지 못했다. 이 프로그램은 충돌하고 사용자를 망칠 것입니다.

하지만 근본 원인 (잘못된 주소 할당)과 해당 표현 (잘못된 주소 호출)이 서로 너무 멀리 떨어져있어 식별하기가 어려울 수 있으므로 문제는 유효합니다.

여기서 내가 조언 할 수있는 것은 "빠르고 시끄럽게 실패하는 것"입니다. 예를 들어, 콜백이 할당 될 때마다 콜백의 테스트 호출을 수행 할 수 있습니다. 이것은 여전히 ​​충돌로 이어지 나, 스택 추적에서 사용자는 어디에서 시작되었는지 볼 수 있습니다.

는 다시, 이것은

+0

저는 RegisterCallback() 함수에서 이미 콜백을하고 있습니다. 제거하기에는 너무 좋았던 개발 테스트로 시작되었습니다. 확인 감사합니다. –

0

다른 사람이 말했듯이, 거기에 확인 할 수있는 방법은 없습니다,하지만 ... 그것은 정말 필요한가 ... 일반 라이브러리 사용자가 기대하는 것이 아니다? 나는 방어적인 프로그래밍에 찬성하지만 모두 (널 포인터가 아닌) 함수에 대한 포인터를 얻을 수있는 유일한 방법은 의 주소를 취하는 것입니다. do 일부 컴파일러에서는 사실에도 불구하고 그러한 경우 진단을 요구하지만 실제로 을 개체에 대한 포인터로 포인터를 함수 포인터로 변환 할 수 있습니다. 그러나 그때조차도, 클라이언트 코드는 망가 뜨리기 위해 명시 적으로 캐스트해야합니다. 그리고 개체와 달리 수명이 0-인 프로그램이므로 수명이 다 된 포인터 — 포인터는 문제가되지 않지만 한 번 유효했던 포인터는 이 아닙니다. 실제로, 유효하지 않은 함수를 의도적으로 제외한 포인터를 가져올 수있는 방법이 없습니다 (함수가있는 DLL을 언로드하는 경우 이 발생하는 유일한 방법 임). 의도적으로 누군가를 망쳤 으면, 을 막을 수있는 방법이 없습니다.