2011-11-06 2 views
7

오늘 아주 이상한 문제가 발생했습니다. 간단히 말해서, 함수가 하나의 값을 반환하면 호출자가 다른 값을 얻습니다.반환시 C 함수 변경 값입니다. 스택이 손상 되었습니까?

connection_receive는 다음과 같이 정의된다
Message* m = NULL; 
m = connection_receive(c); 

은 다음과 같습니다 : 여기

Message* connection_receive(Connection* c) 
{ 
Message* k; 

    if (c->state == CON_STATE_AUTHENTICATED) 
    { 
     pthread_mutex_lock(&c->mutex_in); 

     if (g_queue_is_empty(c->in)) 
      k = NULL; 
     else 
      k = (Message*)g_queue_pop_head(c->in); 

     pthread_mutex_unlock(&c->mutex_in); 
     /* Until here, k is reachable and contains the correct data. */ 
     return k; 
    } 
    else 
     return NULL; 
} 

내가 바로 반환하기 전에 오른쪽 할당 후 정지, gdb를 실행의 :

를 어딘가에 내 코드 주위에 나는에게 전화를 가지고
222   return k; 
(gdb) p k 
$1 = (Message *) 0x7ffff0000950 
(gdb) n 
226 } 
(gdb) n 
main() at src/main.c:57 
57    if (m) 
(gdb) p m 
$2 = (Message *) 0xfffffffff0000950 

물론 0xfffffffff0000950에 액세스하려고하면 세그먼트 화 오류가 발생합니다.

함수를 변경하고 값을 반환하는 대신 두 번째 매개 변수를 사용하여 값을 전달하면이 값이 잘못되었음을 알고 싶습니다.

대단히 감사합니다.

편집 : 이것은 작동하지만 편리하지 않습니다. 그리고 왜 그런 이상한 오류가 일어나는지 알고 싶습니다.

void connection_receive2(Connection* c, Message** m) 
{ 
    if (c->state == CON_STATE_AUTHENTICATED) 
    { 
     pthread_mutex_lock(&c->mutex_in); 

     if (g_queue_is_empty(c->in)) 
      *m = NULL; 
     else 
      *m = (Message*)g_queue_pop_head(c->in); 

     pthread_mutex_unlock(&c->mutex_in); 
    } 
    else 
     *m = NULL; 
} 

edit2 : 해결되었습니다. 모두에게 감사드립니다. 문제는 헤더 파일의 오타였습니다. 경고를 발생시키고 큰 출력과 큰 헤더에서 내가 놓친 것을 처리해야하므로 -Werror를 사용할 수 없습니다.

+0

나는 그것이 한 번 일어났습니다. 'fin'은 반환 값 하나를 보여 주었고 변수에 저장된 값은 다른 값을 나타 냈습니다. 재 컴파일은 저를 위해 그것을 고쳤습니다 (소스를 전혀 변경하지 않았습니다). 내가 추측 할 수있는 가장 좋은 것은 종속 객체 파일이 재 컴파일되지 않았다는 것입니다. 그렇지 않으면 gcc에서 거의 발생하지 않는 버그가있을 수 있습니다. – Kevin

+0

문제를 설명하고 게시하는 [SSCCE] (http://sscce.org/)로 압축해야합니다. 게시 한 코드에는 아무런 문제가 없습니다. 문제는 다른 곳에있다. –

+0

@BrianRoach, 나는 내가 할 수있는 것을 보게 될 것이다. 그것은 큰 프로젝트의 일종입니다. – Victor

답변

5
  1. m은 어떻게 정의됩니까?
  2. 발신자가 올바른 프로토 타입에 액세스 할 수 있습니까?
  3. 어떤 아키텍처를 사용하고 있습니까?

유형과의 불일치가 있고 내 질문 2가 모두 핵심이라고 생각합니다.

포인터가 48 비트 또는 64 비트로 반환됩니다. 그러나 호출자는 int을 얻는다고 생각합니다.이 비트는 32 비트이며 서명되어 있습니다. 다시 포인터로 변환 할 때 값은 부호 확장됩니다.

+4

+1, 꽤 맞습니다 (2) 맞습니다. 이것이 이런 종류의 일을 잡을 것이므로 항상 최대 컴파일 경고 ('-Wall -Werror' gcc)를 사용하여 개발해야하는 이유입니다. –

+0

예, 반환 값의 아래쪽 절반은 매우 똑같습니다. –

+0

@therefromhere \t 죄송합니다. 말씀 드리고 싶지 않습니다. 내 "m"은 또한 Message *입니다. 예, 호출자가 동일한 프로토 타입에 액세스 할 수 있습니다. 실제로 모듈을 테스트하고 있습니다. -Wall도 --Wextra도 나에게 아무것도주지 말고, 그것은 매력처럼 엮어지고있다. 나는 Fedora 15에서 2.6.40.6-0 64bits를 구축하고 실행 중입니다. – Victor

0

큐에서 malloc : ed 객체를 푸시 했습니까? 그렇지 않다면 대신 스택 객체를 푸시하고 항목을 팝업 할 때 이상한 행동으로 끝날 수 있습니다.

+0

이것은 malloc 된 객체입니다. 원래 게시물을 편집하고 잘 작동하는 동일한 정의를 게시했습니다. 정말 이상 하네! – Victor

0

우리는 동일한 문제에 직면했으며 근본 원인은 connection_receive() 함수의 암시 적 선언이었습니다. 그래서 m에 서명하고 저장 한 int가 기본값이되었습니다.

관련 문제