从外部函数返回字符串,同时防止内存泄漏

时间:2017-08-09 10:31:58

标签: c pointers

我试图通过getaddrinfo函数传递一串可变长度,我的代码基本上是:

char *fun(char *ip) {
    struct addrinfo* res;
    int error;

    // resolve the domain name into a list of addresses 
    error = getaddrinfo(ip, NULL, NULL, &res);
    if (error != 0) {   
       if (error == EAI_SYSTEM) {
          perror("getaddrinfo");
       } else {
          fprintf(stderr, "error in getaddrinfo: %s\n", gai_strerror(error));
       }   
       exit(EXIT_FAILURE);
    }

    // go over returned result and do inverse lookup
    char hostname[NI_MAXHOST];
    error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST, NULL, 0, 0); 
    if (error != 0) {
       fprintf(stderr, "error in getnameinfo: %s\n", gai_strerror(error));
    }

    // here I use a pointer in order to pass the string without gcc complain about passing a local var
    char *visname = strdup(hostname);

    /* if I uncomment the below then string is passed correctly */
    // printf("%s\n", hostname);

    freeaddrinfo(res);
    return visname;
 }

int main() {
    ...
    for (int n=0; n<ips; n++) {
       printf("%s\n", fun(ip[n]) );
    }
    return 0;
}

现在这就是事情:

  1. 如果我使用strdup来复制&#34;主机名&#34;到&#34; visname&#34;然后我很确定我需要以某种方式释放visname,但是因为我通过它返回我的问题是返回后是否释放它(内部&#34;有趣&#34;功能)是否正常? / LI>
  2. 如果我打印&#34;主机名&#34;或&#34; visname&#34;里面&#34;有趣&#34;然后传递它 - 这似乎也有效,尽管我的假设是它可能是由于&#34;未定义的行为&#34;?
  3. 由于char * visname是指向本地变量&#34; hostname&#34;的指针,因此不应该:char * visname = hostname work(即返回主机名字符串)?
  4. 修改

    我非常确定我可以将字符串作为参数传递给fun函数然后返回它,但由于它的长度可变,这意味着我需要每次都释放它时间。

    所以我的偏好是somwhow通过函数传递主机名然后我将在main ...中处理它...

1 个答案:

答案 0 :(得分:0)

  1. 不需要在功能之外释放它。

  2. 如果你为它分配了内存(并且有一个有效的字符串),你可以打印它,因为printf不会改变它的参数。

  3. 否,因为局部变量将在函数出口上失效,并且您将返回指向不存在(在非此函数范围内)对象的指针。

    int main() {
       ...
       char *ptr;
       for (int n=0; n<ips; n++) {
           printf("%s\n", (ptr = fun(ip[n])) );
           free(ptr);
        }
        return 0;
    }
    
  4. 编辑后;

        int main() {
           ...
           char ptr[MAXHOSTNAMESIZE +1];
           for (int n=0; n<ips; n++) {
               printf("%s\n", (fun(ip[n], ptr)) );
            }
            return 0;
        }
    

        int main() {
           ...
           char *ptr = malloc(MAXHOSTNAMESIZE +1);
           for (int n=0; n<ips; n++) {
               printf("%s\n", (fun(ip[n], ptr)) );
            }
            free(ptr)
            return 0;
        }
    
    char *fun(char *ip, char *buff) {
        struct addrinfo* res;
        int error;
    
        ///......
        error = getnameinfo(res->ai_addr, res->ai_addrlen, buff, NI_MAXHOST, NULL, 0, 0);
        if (error != 0) {
            fprintf(stderr, "error in getnameinfo: %s\n", gai_strerror(error));
        }
        //....
        return buff;
    }