Damian
Damian

Reputation: 789

ANSI C - passing data from function to a CHAR pointer

I have a problem with understanding how "char*" works in different files. For example, i have a simple CURL function that helps me sending data to other HTTP WEB SERVICES. But i also need to recieve, here is the function located in 'curlate.h' :

#include <stdio.h> 
#include <curl/curl.h>

struct string
{
    char * ptr;
    size_t len;
};

void init_string(struct string * s)
{
    s - > len = 0;
    s - > ptr = malloc(s - > len + 1);
    if (s - > ptr == NULL)
    {
        fprintf(stderr, "malloc() failed\n");
        exit(EXIT_FAILURE);
    }
    s - > ptr[0] = '\0';
}

size_t writefunc(void * ptr, size_t size, size_t nmemb, struct string * s)
{
    size_t new_len = s - > len + size * nmemb;
    s - > ptr = realloc(s - > ptr, new_len + 1);
    if (s - > ptr == NULL)
    {
        fprintf(stderr, "realloc() failed\n");
        exit(EXIT_FAILURE);
    }
    memcpy(s - > ptr + s - > len, ptr, size * nmemb);
    s - > ptr[new_len] = '\0';
    s - > len = new_len;

    return size * nmemb;
}

char* curlate_and_print(char url[])
{
    //printf("Curlating ... %s : ",url);
    CURL *curl;
    CURLcode res;

    struct string s;
    init_string(&s);

    curl = curl_easy_init();
    if(curl)
    {
        curl_easy_setopt(curl, CURLOPT_URL, url);
        /* example.com is redirected, so we tell libcurl to follow redirection */ 
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);

        /* Perform the request, res will get the return code */ 
        res = curl_easy_perform(curl);

        /* Check for errors */ 
        if(res != CURLE_OK)
        {
            curl_easy_strerror(res);
        }
        else
        {
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
            res = curl_easy_perform(curl);

            // *** THE FUNCTION PRINTS THE RESULT HERE WITH NO PROBLEM
            printf("\nCURL_STRING BEGIN\n%s\nCURL_STRING END\n", s.ptr);
            free(s.ptr);
        }

        /* always cleanup */ 
        curl_easy_cleanup(curl);

    }

    return s.ptr;
}

The script works with no problems, it is printing stuff, but i also return the value like this return s.ptr; and i want to use this string data in main.c.

Now, in main.c i call the curlate_and_print function, it is printing data, but no matter what i do, i cannot print it in main.c !

char* content2 = curlate_and_print(link_to_curlate);

Why in the earth char* content2 is empty in main.c? s.ptr is not empty, it has the content result.

Here is what i have in main.c :

if(debug >= 1)  printf("Testing, curlating %s : \n",link_to_curlate);
// in content2 sa se verse output-ul din curlate_and_print(link_to_curlate);
char* content2 = curlate_and_print(link_to_curlate);

printf("\n");

printf(">%s\n",content2); // *** I GET EMPTY STRING
printf(">%s\n",content2); // *** I GET EMPTY STRING
printf(">%s\n",content2); // *** I GET EMPTY STRING
printf(">%s\n",content2); // *** I GET EMPTY STRING
printf(">%s\n",content2); // *** I GET EMPTY STRING

How can i solve this?

The problem is, i think, that i cannot understand what the char* content2 = "asdasd" does, for me is like saying in JAVA 'String java = "asdasd";', even though i know that is a char pointer.

Thanks.

Upvotes: 0

Views: 190

Answers (2)

Gophyr
Gophyr

Reputation: 406

Try changing the return statement of your function to this:

return strdup(s.ptr);

This will automatically malloc the string but you do not have to worry about that. It will basically duplicate the string for you. s.ptr is a local variable; if you want to return it make it heap-allocated and say return s->ptr. You have to do this because s.ptr is local, thus after the function returns, you can no longer access the stack memory pointed to by s.ptr.

Upvotes: 1

Drew McGowen
Drew McGowen

Reputation: 11706

The problem is when you first print the string (inside curlate_and_print), you immediately free the string buffer (the call free(s.ptr)). After freeing it, attempts to dereference the pointer results in undefined behavior. In your case, the string appears empty.

Upvotes: 1

Related Questions