双指针指向的指针的值丢失(c代码)

时间:2016-08-16 17:11:10

标签: c pointers sip sdp double-pointer

我正在研究一种对SIP消息进行一些操作的c代码,以便更具体地从消息的SDP主体中提取值。我不是c的专业人士,但是利用我在大学课程中获得的知识,我编写了我的代码。

问题是在函数get_m_line_f(str body)中创建了一个双指针并从中返回。这个双指针指向str *类型的两个指针。他们中的每一个都有一个char指针,它指向我想要从我的刺痛中获得的块的开始(块恰好是m = ...... \ r \ n)以及该块的长度。 / p>

当我检查函数中指针指向的值时它们是正确的,但是当我检查返回的双指针中的值时它们是错误的,尽管你可以看到从双指针内部指向的地址没改变。请检查下面的代码和输出,您将更好地了解问题。提前谢谢

这是我主要功能的一部分:

    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:13@10.10.1.13 SIP/2.0 \r\n"
        "Via: SIP/2.0/UDP 10.10.1.99:5060;branch=z9hG4bK343bf628;rport\r\n"
        "From: \"Test 15\" <sip:15@10.10.1.99>;tag=as58f4201b\r\n"
        "To: <sip:13@10.10.1.13>\r\n"
        "Contact: <sip:15@10.10.1.99>\r\n"
        "Call-ID: 326371826c80e17e6cf6c29861eb2933@10.10.1.99\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 body)函数是

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;
}

str结构非常简单:

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

1 个答案:

答案 0 :(得分:0)

我修改了你的程序,如下所示。有两个错误。

  • 一个错误在于你如何解决m_lines,但我认为你的困惑来自于思考&#34;双指针&#34;,当你真正拥有的 - 实际上 - 是指向数组的指针。

  • 有效&#34;指向数组的指针&#34;是m_lines。它的元素是指针。不幸的是,它们是指向局部变量m_audiom_video的指针。该存储不可用于调用功能。当get_m_line_f返回时,不再定义m_lines元素指向的内存。

我通过整理样式和使用数组表示法使问题更加明显。我的更改以// - 样式注释表示。

最糟糕的问题是这一行:

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

m_lines定义为str**,指向2个指针的指针。为了说明数组符号如何澄清问题,上述内容等同于

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

这意味着您要分配到m_lines[12]左右,可能不是您的意思,绝对不是您分配的内容!

在尝试调试时,您打印出值。当然,你完全按照你指定的方式取消引用m_lines,并且对于那个简短而闪亮的时刻,你踩踏的记忆仍然具有你放在那里的东西。我更改了作业并单独留下了打印逻辑;它现在将显示你期望的陌生感。

您可以通过更改函数来返回str数组。然后你可以使用该数组,消除局部变量。 IOW,而不是

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

m_lines定义为

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

那样,

  • 您可以参考m_lines[0]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;
}