2016-08-16 9 views
-1

SIP 메시지의 일부 조작을보다 구체적으로 수행하는 C 코드에서 작업하면서 메시지의 SDP 본문에서 값을 추출합니다. 저는 전문직이 아니지만 대학에서 얻은 지식을 사용하여 제 코드를 썼습니다.이중 포인터가 가리키는 포인터의 값이 손실되었습니다 (C 코드)

문제는 get_m_line_f (str 본문) 함수 내에서 이중 포인터가 만들어지고 그 포인터가 반환된다는 것입니다. 이 이중 포인터는 str * 유형의 두 포인터를 가리 킵니다. 그들 각각은 내가 쓴 (덩어리는 m = ...... \ r \ n 일 것입니다) 덩어리의 길이와 그 덩어리의 길이를 가리키는 숯 포인터를 가지고 있습니다.

포인터가 가리키는 값이 올바른지 whith 함수에서 확인했을 때 반환 된 double 포인터의 값을 확인하면 두 번 내부에서 가리키는 주소를 볼 수 있습니다. 포인터가 변경되지 않았습니다. 아래의 코드와 출력을 확인하면 문제를 더 잘 이해할 수 있습니다.

int main(void) { 

str body; 
str ip; 
str ports; 
str m_line; 

str *m_line_ptr_one; 
str *m_line_ptr_two; 

str *port_ptr_one; 
str *port_ptr_two; 

str **m_lines; 
str **double_ptr_two; 

char msg[] = "INVITE sip:[email protected] SIP/2.0 \r\n" 
     "Via: SIP/2.0/UDP 10.10.1.99:5060;branch=z9hG4bK343bf628;rport\r\n" 
     "From: \"Test 15\" <sip:[email protected]>;tag=as58f4201b\r\n" 
     "To: <sip:[email protected]>\r\n" 
     "Contact: <sip:[email protected]>\r\n" 
     "Call-ID: [email protected]\r\n" 
     "CSeq: 102 INVITE\r\n" 
     "User-Agent: Asterisk PBX\r\n" 
     "Max-Forwards: 70\r\n" 
     "Date: Wed, 06 Dec 2009 14:12:45 GMT\r\n" 
     "Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER,SUBSCRIBE, NOTIFY\r\n" 
     "Supported: replaces\r\n" 
     "Content-Type: application/sdp\r\n" 
     "Content-Length: 258\r\n" 
     "\r\n" 
     "v=0\r\n" 
     "o=root 1821 1821 IN IP4 10.10.1.99\r\n" 
     "s=session\r\n" 
     "c=IN IP4 10.10.1.99\r\n" 
     "t=0 0\r\n" 
     "m=audio 11424 RTP/AVP 0 8 101\r\n" 
     "m=video 12324 RTP/AVP 0 8 101\r\n" 
     "c=IN IP4 10.10.1.99\r\n" 
     "a=sendrcv\r\n"; 


body.s = msg; 
body.len = strlen(msg); 

m_lines = get_m_line_f(body); 

printf("the addresses after they are returned\naudio: %p\nvideo: %p\n",*m_lines,*(m_lines + sizeof(struct str*))); 

printf("Output from the pointer after it is returned\n %.*s\n", (*m_lines)->len,(*m_lines)->s); 
printf("Output from the pointer after it is returned\n %.*s\n", (*(m_lines + sizeof(struct str*)))->len, (*(m_lines + sizeof(struct str*)))->s); 


double_ptr_two = get_m_port(m_lines); 

get_m_line_f (STR 본체) 함수는 STR 구조체가

struct str **get_m_line_f(str body){ 


str m_audio; 
str *m_audio_ptr; 
m_audio_ptr = &m_audio; 

str m_video; 
str *m_video_ptr; 
m_video_ptr = &m_video; 

str **m_lines; 
m_lines = (str**)malloc(2*sizeof(str*)); 


if(m_lines == NULL){ 
    printf("cannot allocate PKG memory\n"); 
    return NULL; 
} 


int len; 

if (body.s == 0){ 
    printf("Failed to get message body\n"); 
    return NULL; 
} 


if (body.len == 0){ 
    printf("message body has zero length\n"); 
    return NULL; 
} 


for (int i=0;i<=body.len;++i){ 
    if(*(body.s+i) == 'm' && *(body.s+i+1) == '='){ 
     if(strncmp(body.s+i+2,"audio",strlen("audio")) == 0){ 
       m_audio.s = body.s+i; 
     } else if(strncmp(body.s+i+2,"video",strlen("video")) == 0){ 
      m_video.s = body.s+i; 
     } 
    } 
} 


if(m_audio.s != NULL){ 
    for(len=0;*(m_audio.s+len) != '\n';++len); 
    m_audio.len = len; 
    *(m_lines) = m_audio_ptr; 
} else{ 
    printf("No \"m=audio\" line is found\n"); 
    return NULL; 
} 

if(m_video.s != NULL){ 
     for(len=0;*(m_video.s+len) != '\n';++len); 
     m_video.len = len; 
     *(m_lines + sizeof(struct str*)) = m_video_ptr; 
    } else{ 
     printf("No \"m=video\" line is found\n"); 
     return NULL; 
    } 

printf("output from the double pointer in the function where its created\n %.*s\n", (*m_lines)->len,(*m_lines)->s); 
printf("output from the double pointer in the function where its created\n %.*s\n", (*(m_lines + sizeof(struct str*)))->len, (*(m_lines + sizeof(struct str*)))->s); 


printf("Checking the addresses to be returned\naudio: %p\nvideo: %p\n",*m_lines,*(m_lines + sizeof(struct str*))); 

return m_lines; 
} 

매우 간단하다 :

typedef struct str{ 
    char* s; 
    int len; 
} str; 
사전에 감사

이 내 주 연료 소모량의 일부입니다

내 코드의 출력은 다음과 같습니다 :

output from the double pointer in the function where its created 
m=audio 11424 RTP/AVP 0 8 101 

output from the double pointer in the function where its created 
m=video 12324 RTP/AVP 0 8 101 

Checking the addresses to be returned 
audio: 0x7fff52db0848 
video: 0x7fff52db0830 
the addresses after they are returned 
audio: 0x7fff52db0848 
video: 0x7fff52db0830 
Output from the pointer after it is returned 
m=audio 11424 RTP/AVP 0 8 101 

m=video 12324 RTP/AVP 0 8 101 

c=IN IP4 10.10.1.99 

a=sendrcv 
+0

수명이 끝난 후 자동 저장 기간이있는 개체에 액세스하는 정의되지 않은 동작입니다. – EOF

답변

0

아래 프로그램을 수정했습니다. 두 가지 오류가 있습니다.

  • 하나의 오류는 m_lines를 해결하는 방법에 있지만 나는 당신의 혼란은 당신이 정말로 무엇을 할 때 "더블 포인터"에 대해 생각에서 발생 생각 - 효과 - 배열에 대한 포인터입니다.

  • 유효 "어레이에 대한 포인터"는 m_lines입니다. 그 요소는 포인터입니다. 불행하게도 이들은 로컬 변수 m_audiom_video을 가리키는 포인터입니다. 저장 기능을 호출 기능에서 사용할 수 없습니다. get_m_line_f이 반환되면 m_lines 요소가 가리키는 메모리는 더 이상 정의되지 않습니다.

스타일을 약간 깔끔하게하고 배열 표기법을 사용하여 문제를 더욱 분명하게 나타 냈습니다. 내 변경 사항은 //- 스타일 댓글로 표시됩니다.

*(m_lines + sizeof(struct str*)) = m_video_ptr; 

m_linesstr**로 정의됩니다 2 포인터에 대한 포인터 :

최악의 문제는이 라인입니다. 배열 표기법이 문제를 명확하게하는 방법을 설명하기 위해, 위는 m_lines[12]에 할당하거나, 그래서 아마 당신이 의미없는 무엇, 그리고 확실히 당신이 할당 무엇을하고 의미

m_lines[sizeof(struct str*)] = m_video_ptr; 

에 해당합니다!

디버깅을 시도 할 때 값을 인쇄합니다. 물론, m_lines을 당신이 할당 한 방식대로 역 참조하십시오. 그리고 그 요약을 위해 당신이 밟은 기억은 당신이 거기에 놓은 것을 가지고 있습니다. 과제를 변경하고 인쇄 논리 만 남겼습니다. 이제는 예상했던 낯설음이 보일 것입니다.

대신 str의 배열을 반환하도록 함수를 변경하면 도움이됩니다. 그런 다음 해당 배열을 제자리에서 사용하여 로컬 변수를 제거 할 수 있습니다. IOW,

str **m_lines = malloc(2 * sizeof(str*)); // do not cast malloc 

정의 대신에 당신은 할당 한 m_lines

  • m_lines[0]

    • 당신이 참조 할 수 있습니다,

      str *m_lines = calloc(2, sizeof(str)); 
      

      그 방법으로하고 m_lines[1]저장이 가리키는 모든 반환 할 변수에 의해.

    일반적으로 로컬 변수의 주소 할당은 문제가됩니다. 때로는 함수에 주소를 전달하기도합니다. 하나를 반환하는 것은 간접적으로는 거의 항상 오류입니다.

    여기에 프로그램이 다소 패치되었지만 정확하지 않습니다. 함수 정의를 변경할지 또는 m_audiom_video을 힙에 할당할지 결정해야합니다.

    #include <stdbool.h> 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    
    typedef struct str { 
        char *s; // put the * by the variable. 
        int len; 
    } str; 
    
    struct str ** 
    get_m_line_f(str body) 
    { 
        // initialize when defining 
        str m_audio, *m_audio_ptr = &m_audio; 
        str m_video, *m_video_ptr = &m_video; 
    
        str **m_lines = malloc(2 * sizeof(str*)); // do not cast malloc 
    
        if(m_lines == NULL){ 
        printf("cannot allocate PKG memory\n"); 
        return NULL; 
        } 
    
        if (body.s == NULL) { // s is a pointer 
        printf("Failed to get message body\n"); 
        return NULL; 
        } 
    
    
        if (body.len == 0){ 
        printf("message body has zero length\n"); 
        return NULL; 
        } 
    
        int len; 
    
        for (int i=0; i <= body.len; ++i) { 
        // could use 0 == memcmp(body.s+i, "m=", 2) 
        if (body.s[i] == 'm' && body.s[i+1] == '=') { 
         // use compile-time constants 
         static const char audio[] = "audio", video[] = "video"; 
         if (strncmp(body.s+i+2, audio, sizeof(audio) - 1) == 0) { 
         m_audio.s = body.s+i; 
         } else if(strncmp(body.s+i+2, video, sizeof(video) - 1) == 0) { 
         m_video.s = body.s+i; 
         } 
        } 
        } 
    
        if (m_audio.s != NULL) { 
        for (len=0; m_audio.s[len] != '\n'; ++len); 
        m_audio.len = len; 
        m_lines[0] = m_audio_ptr; 
        } else{ 
        printf("No \"m=audio\" line is found\n"); 
        return NULL; 
        } 
    
        if(m_video.s != NULL) { 
        for(len=0;*(m_video.s+len) != '\n';++len); 
        m_video.len = len; 
        if (false) { // vvv addressing error here vvv 
         *(m_lines + sizeof(struct str*)) = m_video_ptr; 
        } else { 
         m_lines[1] = m_video_ptr; 
        } 
        } else { 
        printf("No \"m=video\" line is found\n"); 
        return NULL; 
        } 
    
        printf("output from the double pointer in the function where its created\n %.*s\n", (*m_lines)->len,(*m_lines)->s); 
        printf("output from the double pointer in the function where its created\n %.*s\n", (*(m_lines + sizeof(struct str*)))->len, (*(m_lines + sizeof(struct str*)))->s); 
    
    
        printf("Checking the addresses to be returned\naudio: %p\nvideo: %p\n", (void*)*m_lines, (void*)*(m_lines + sizeof(struct str*))); 
    
        return m_lines; 
    } 
    
  • +0

    변경 사항은 내 코드의 동일한 출력을 제공하므로 문제가 해결되지 않았습니다. Howerver 귀하의 commints 정말 귀중하고 나는 그들로부터 혜택을. 고마워. –