2012-12-18 8 views
4

Linux의 경우. dlsym (3) Linux 매뉴얼 페이지dlsym()에 의해 반환 된 심볼의 값이 null 일 수있는 이유는 무엇입니까?

*Since the value of the symbol could actually be NULL 
    (so that a NULL return from dlsym() need not indicate an error),* 

이유는 무엇인가? 나는 코드를 검토 중이며 dlerror를 사용하여 먼저 정리하고, 다음에 dlsym을 그리고, 오류를 확인하기 위해 dlerror를 사용하여 조각을 찾았습니다. 그러나 호출 전에 결과 함수가 null인지 확인하지 않습니다.

  • dlerror();
  • a_func_name = ... dlsym (...);
  • if (dlerror()) goto end;
  • a_func_name (...); // a_func_name == NULL 인 경우에는 확인하지 않습니다.

나는 그래서 그냥 수표를 추가 할 수있는 옵션이없는 단지 검토입니다. 아마도 저자는 NULL을 반환 할 수 없다는 것을 알고 있습니다. 내 직업은 그것을 도전하는 것이지만이 반환 값을 유효한 NULL로 만들 수 있는지 알지 못하므로이 코드의 컨텍스트에서 조건이 충족 될 수 있는지 확인할 수 있습니다. Google에서 읽을만한 것을 찾지 못했지만 훌륭한 문서를 가리키는 포인터가 무엇인지 명확하게 설명하고 싶지 않으면 충분합니다.

+1

어셈블러에서 또는 GCC 특정 트릭을 사용하여 주어진 심볼을 주소 0에 정의 할 수 있으며 심볼을'dlsym' 할 수 있습니다. –

+0

알았어요. 감사. – bokusama

답변

1

오류없이 반환되면 포인터는 유효하며 NULL은 공유 객체의 임의 포인터와 거의 불법입니다. 잘못된 기능, 데이터 또는 뭐든간에.

+3

리턴 값이 공유 변수 (또는 함수)의 * value * 일 경우 이는 의미가 있습니다. 그러나 그것은 주소가되어야합니다. 그렇지 않습니까 (또는 깃발에 달려 있습니까)? 음, 아마도 실제로 주소 테이블에서 값을 읽는 중입니다. 바이너리는 해당 테이블에서 0 (또는 잘못된 포인터)을 갖도록 편집 될 수 있습니다. –

+0

글쎄, 잘 모르겠지만 심볼을 내보낼 수 없어 절대 주소가 있습니까? –

+0

실제로. 고맙습니다. – bokusama

-1

dlerror()은 마지막 호출의 상태가 아니라 마지막 오류를 반환합니다. 그래서 만약 당신이 보여줄 코드가 dlsym()에서 결과를 잠재적으로 얻을 수 있으며 (대기열에 여전히 하나 있기 때문에) 오류가 있다고 생각해서 바보가 될 수도 있습니다. dlerror의 목적은 사람이 읽을 수있는 오류 메시지를 제공하는 것입니다. 결과를 인쇄하지 않으면 잘못 사용하고있는 것입니다.

+3

가장 최근의 오류 변수를 지우는 것이 바로 * dlsym 이전에'dlerror()'호출의 목적입니다. 대기열이 없습니다 (맨 페이지를 믿을 수있는 경우). –

+0

아, 그리워. 그래, 이건 말도 안되지만 맞아. 'dlsym'은 에러시 NULL을 반환하는 것으로 문서화되어 있지만,'dlerror'의 NULL이 아닌 결과는 동등합니다 (threadsafety 버그와 같은 것을 제외하고 - 다른 스레드가 동일한 말도 안되는 경우 분명히 경쟁이 있습니다). 그것은 여전히 ​​API의 남용입니다. –

+0

확실히 모든 스레드는 자체 오류 변수 복사본을 가지고 있습니다. 어쨌든 이것은 학대가 아니라 API를 호출하는 올바른 방법입니다. 비교 :'errno = 0; int a = itoa (s); 만약 if (a)'가's = "0";'s '= "Garbage";를 구별 할 수 없기 때문에 if (errno) ...'. –