• C

Error while Returning an Array of char* from Function

Hello,

i want to implement a function, which returns a array of char* with well formated IPs from an DNS-Lookedup Hostname.
I created the attached code and get the following warnings while compiling.
The Array needs to be dynamical because the count of IPs returned by the DNS Lookup is not known at compile-time.
Can anyone help to solve the warnings?

In function âgetipâ:
warning: assignment makes integer from pointer without a cast
warning: passing argument 1 of âsprintfâ makes pointer from integer without a cast
warning: assignment makes integer from pointer without a cast
warning: passing argument 1 of âstrcpyâ makes pointer from integer without a cast

char *getip(char *dnsname)
{
struct hostent *hostinfo;
 
if (hostinfo = gethostbyname (dnsname))
{
        printf ("Address length:     %d\n", hostinfo->h_length);
 
int ips=0;
 
while (hostinfo->h_addr_list[ips]!=NULL)
ips++;
 
char *ergebnis = (char *)malloc( ips * sizeof( char ) );
 
int i;
while (hostinfo->h_addr_list[i]!=NULL)
{
ergebnis[i]=malloc(16);
sprintf(ergebnis[i],"%d.%d.%d.%d",(unsigned char)hostinfo->h_addr_list[i][0],\
                                    (unsigned char)hostinfo->h_addr_list[i][1],\
                                    (unsigned char)hostinfo->h_addr_list[i][2],\
                                    (unsigned char)hostinfo->h_addr_list[i][3]);
i++;
}
return ergebnis;
} else
{
char *ergebnis = (char *)malloc( sizeof( char ) );
ergebnis[0]=malloc(6);
strcpy(ergebnis[0],"failed");
return ergebnis;
}
}

Open in new window

LVL 2
ktd85Asked:
Who is Participating?
 
evilrixConnect With a Mentor Senior Software Engineer (Avast)Commented:
Your heap allocated array has the wrong signature. You care creating an array of char not char *

char *ergebnis = (char *)malloc( ips * sizeof( char ) );

Should be something like...

char **ergebnis = malloc( ips * sizeof( char *) );

Note, you don't need to car the return of malloc in C since it is a void * it will automatically convert to any pointer type.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> you don't need to car the return of malloc
Typo: you don't need to cast the return of malloc
0
 
ktd85Author Commented:
thanks for your Quick response.

Now my code looks like below and now i get the following warnings:
warning: assignment makes integer from pointer without a cast
warning: passing argument 1 of âstrcpyâ makes pointer from integer without a cast

void *getip(char *dnsname)
{
struct hostent *hostinfo;
 
if (hostinfo = gethostbyname (dnsname))
{
        printf ("Address length:     %d\n", hostinfo->h_length);
 
int ips=0;
 
while (hostinfo->h_addr_list[ips]!=NULL)
ips++;
 
char **ergebnis = malloc( ips * sizeof( char *) );
//char *ergebnis = (char *)malloc( ips * sizeof( char ) );
 
int i;
while (hostinfo->h_addr_list[i]!=NULL)
{
ergebnis[i]=malloc(16);
sprintf(ergebnis[i],"%d.%d.%d.%d",(unsigned char)hostinfo->h_addr_list[i][0],\
                                    (unsigned char)hostinfo->h_addr_list[i][1],\
                                    (unsigned char)hostinfo->h_addr_list[i][2],\
                                    (unsigned char)hostinfo->h_addr_list[i][3]);
i++;
}
return ergebnis;
} else
{
char *ergebnis = (char *)malloc( sizeof( char ) );
ergebnis[0]=malloc(6);
strcpy(ergebnis[0],"failed");
return ergebnis;
}
}

Open in new window

0
Improve Your Query Performance Tuning

In this FREE six-day email course, you'll learn from Janis Griffin, Database Performance Evangelist. She'll teach 12 steps that you can use to optimize your queries as much as possible and see measurable results in your work. Get started today!

 
evilrixSenior Software Engineer (Avast)Commented:
You didn't change line 30

char *ergebnis = (char *)malloc( sizeof( char ) );

:)
0
 
ktd85Author Commented:
Hi,

i changed the code to the following.
The errors are gone.
But how to access the result of the function?
void *getip(char *dnsname)
{
struct hostent *hostinfo;
 
if (hostinfo = gethostbyname (dnsname))
{
        printf ("Address length:     %d\n", hostinfo->h_length);
 
int ips=0;
 
while (hostinfo->h_addr_list[ips]!=NULL)
ips++;
 
char **ergebnis = malloc( ips * sizeof( char *) );
 
//char *ergebnis = (char *)malloc( ips* sizeof( char ) );
 
int i;
while (hostinfo->h_addr_list[i]!=NULL)
{
ergebnis[i]=malloc(16);
sprintf(ergebnis[i],"%d.%d.%d.%d",(unsigned char)hostinfo->h_addr_list[i][0],\
                                    (unsigned char)hostinfo->h_addr_list[i][1],\
                                    (unsigned char)hostinfo->h_addr_list[i][2],\
                                    (unsigned char)hostinfo->h_addr_list[i][3]);
i++;
}
return ergebnis;
} else
{
char **ergebnis = malloc( sizeof( char ) );
ergebnis[0]=malloc(6);
strcpy(ergebnis[0],"failed");
return ergebnis;
}
}

Open in new window

0
 
evilrixConnect With a Mentor Senior Software Engineer (Avast)Commented:
BTW: Shouldn't the function return char ** too?

>> But how to access the result of the function?
I don't get what you mean. DO you mean something like this...?

char ** ppErgebnis = char **getip(char *dnsname);

char * pErgebnis1 = ppErgebnis[0];
char * pErgebnis2 = ppErgebnis[2];
...
char * pErgebnisN = ppErgebnis[N]; // Where N is the last element in the array

0
 
ktd85Author Commented:
Thanks for the example how to get access to the functions return value.

But now the Call of the function results in a segmentation fault.

My actual Function code attached.
char **getip(char *dnsname)
{
struct hostent *hostinfo;
 
if (hostinfo = gethostbyname (dnsname))
{
        printf ("Address length:     %d\n", hostinfo->h_length);
 
int ips=0;
 
while (hostinfo->h_addr_list[ips]!=NULL)
ips++;
 
char **ergebnis = malloc( ips * sizeof( char *) );
 
int i;
while (hostinfo->h_addr_list[i]!=NULL)
{
ergebnis[i]=malloc(16);
sprintf(ergebnis[i],"%d.%d.%d.%d",(unsigned char)hostinfo->h_addr_list[i][0],\
                                    (unsigned char)hostinfo->h_addr_list[i][1],\
                                    (unsigned char)hostinfo->h_addr_list[i][2],\
                                    (unsigned char)hostinfo->h_addr_list[i][3]);
printf("%s\n",ergebnis[i]);
i++;
}
return ergebnis;
} else
{
char **ergebnis = malloc( sizeof( char ) );
ergebnis[0]=malloc(6);
strcpy(ergebnis[0],"failed");
return ergebnis;
}
}

Open in new window

0
 
evilrixSenior Software Engineer (Avast)Commented:
Can you post all your code (or at least a working example that generates the problem please? I suspect you are trying to read beyond the end of the returned array.
0
 
Infinity08Connect With a Mentor Commented:
>> int i;

You should always initialize variables (in this case to 0)


>> char **ergebnis = malloc( sizeof( char ) );

You don't want to allocate just one byte of memory (sizeof(char)). You want to allocate enough room for a char*, so use sizeof(char*)


>> ergebnis[0]=malloc(6);
>> strcpy(ergebnis[0],"failed");

The string "failed" needs 7 characters (6 + 1 for the trailing null), so use malloc(7).


All of these problems can cause a segmentation fault or other type of crash.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> You don't want to allocate just one byte of memory (sizeof(char)).
Argg... well spotted -- I've already pointed that out twice :)

>> The string "failed" needs 7 characters (6 + 1 for the trailing null), so use malloc(7).
Again, good spot :)
0
 
Infinity08Commented:
;)
0
 
ktd85Author Commented:
Thank you very very much.
After correcting the issues you pointed out the function is working fine. The working source code is attached.

The following code is used to call and test the function:
        char **ppErgebnis=getip("www.google.de");
        printf ("%s\n%s\n%s",ppErgebnis[0],ppErgebnis[1],ppErgebnis[2]);
 
BTW: What about the Memory allocted should i call free(ppErgebnis) after processing the output?
char **getip(char *dnsname)
{
struct hostent *hostinfo;
 
if (hostinfo = gethostbyname (dnsname))
{
        printf ("Address length:     %d\n", hostinfo->h_length);
 
int ips=0;
 
while (hostinfo->h_addr_list[ips]!=NULL)
ips++;
 
char **ergebnis = malloc( ips * sizeof( char *) );
 
int i=0;
while (hostinfo->h_addr_list[i]!=NULL)
{
ergebnis[i]=malloc(16);
sprintf(ergebnis[i],"%d.%d.%d.%d",(unsigned char)hostinfo->h_addr_list[i][0],\
                                    (unsigned char)hostinfo->h_addr_list[i][1],\
                                    (unsigned char)hostinfo->h_addr_list[i][2],\
                                    (unsigned char)hostinfo->h_addr_list[i][3]);
i++;
}
return ergebnis;
} else
{
char **ergebnis = malloc( sizeof( char*) );
ergebnis[0]=malloc(7);
strcpy(ergebnis[0],"failed");
return ergebnis;
}
}

Open in new window

0
 
evilrixConnect With a Mentor Senior Software Engineer (Avast)Commented:
>> What about the Memory allocted should i call free(ppErgebnis) after processing the output?
You need to free it and all the elements it contains since they too are also allocated by malloc, right?

char **ergebnis = malloc( ips * sizeof( char *) );
ergebnis[i]=malloc(16);

So you need to free ergebnis[i] first and then ergebnis.

Make sense?
0
 
ktd85Author Commented:
Should i freed it inside the function?
Can the result be accessed by the procedure calling that function?
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> Should i freed it inside the function?
Well you can't if you want to use it outside the function.

>> Can the result be accessed by the procedure calling that function?
Not if you free it. You'll have to do this outside of the function.
0
 
ktd85Author Commented:
Thanks thats what i wanted to know.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> Thanks thats what i wanted to know.
No worries :)
0
 
evilrixSenior Software Engineer (Avast)Commented:
ktd85,

Any reason you've asked for the Q to be closed in 7 days? Are you unhappy with the answers given?

If you'd like to finalize this question now you can accept those answers (note you can accept more than one answer) that helped you and apportion the points as you see fit. If you are unsure the help will guide you: http://www.experts-exchange.com/help.jsp#hi331 If you are still unsure please post back here and either myself or Infinity08 will be happy to assist you.

Alternatively, if you'd like to receive help from a moderator please click the link on the top right of this page (just below your question text) labeled 'Report Abuse" and this will bring this thread to their attention and they will be only too happy to guide you.

Thanks.

-Rx.

0
 
Infinity08Commented:
Make sure you free all data correctly ... ie. every malloc has to have a corresponding free (so, free ergebnis[i] for every i in a loop, and then free ergebnis).

Btw :

>>         printf ("%s\n%s\n%s",ppErgebnis[0],ppErgebnis[1],ppErgebnis[2]);

Make sure that the function actually returned 3 strings, before trying to print 3. If it returned less, then this might cause another segmentation fault or worse.

In other words, you might want to change the signature of your function to include the size ...
0
 
ktd85Author Commented:
Sorry i faild closing the question.
The answers were all fine don't worrie.

I think I've corrected the issue right now.
0
 
Infinity08Commented:
That's ok, ktd85 :) All's fine !
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> Sorry i faild closing the question.
No worries, just wanted to make sure you had all you needed :)

>> The answers were all fine don't worrie.
Good stuff

>> I think I've corrected the issue right now.
Indeed you have, many thanks.
0
 
ktd85Author Commented:
Sorry to bother you again.
As i tried to implement a method that displays the returned values it failed again in segmentation fault.

Code attached below.
void printarray(char **ppErgebnis)
{
int i=0;
if (ppErgebnis!=NULL)
while (ppErgebnis[i]!=NULL)
 {
   printf("%s\n",ppErgebnis[i]);
   i++;
 }
}

Open in new window

0
 
evilrixSenior Software Engineer (Avast)Commented:
>> while (ppErgebnis[i]!=NULL)
This test assumes that at some point you'll hit a NULL within the bounds of the array ppErgebnis. Do you ensure when you create ppErgebnis you initialize the unused elements to NULL and there will always be at least one set to NULL?
0
 
ktd85Author Commented:
No, that was the point! Thanks.
0
 
ktd85Author Commented:
Would it statisfy the requirements if i change the line allocations space for the list:
char **ergebnis = malloc( (ips+1) * sizeof( char *) );

and add the following line at the end of the while-loop?
ergebnis[i+1]=NULL;

Because i changed this and get a segmentation fault...

Is there any console-based ide under debian which can handle breakpoints?
0
 
Infinity08Commented:
>> char **ergebnis = malloc( (ips+1) * sizeof( char *) );

Yes.


>> and add the following line at the end of the while-loop?
>> ergebnis[i+1]=NULL;

i has already been incremented - you don't need to increment it again, so :

        ergebnis[i] = NULL;

or even :

        ergebnis[ips] = NULL;
0
 
ktd85Author Commented:
Thanks.
Sorry for asking so stupid questions...
Do you thing it would be easier if i move to c++?
What about the compatibility of C code to C++ code?
0
 
Infinity08Commented:
>> Do you thing it would be easier if i move to c++?

It could be if you use a vector of strings for example ...


>> What about the compatibility of C code to C++ code?

C code will be accepted by a compliant C++ compiler.
0
 
ktd85Author Commented:
Is g++ a compliant compiler?
Is there any console-based ide under debian which can handle breakpoints?
0
 
evilrixSenior Software Engineer (Avast)Commented:
Sorry, I had to drive home -- I see I8 has been very helpful though :)

>> Is there any console-based ide under debian which can handle breakpoints?
Try ddd
http://www.gnu.org/software/ddd/


>> C code will be accepted by a compliant C++ compiler
Sorry to disagree -- MOST but not all C code will be accepted. For example, in C++ you have to cast your void * in C you don't.

/* Works in C but not C++ */
int main()
{
	void * pv = 0;
	int * pi = pv;
 
	return 0;
}

Open in new window

0
 
evilrixSenior Software Engineer (Avast)Commented:
>>>> Is there any console-based ide under debian which can handle breakpoints?
>>Try ddd

Sorry, I've just re-read the Q and saw the word console -- missed it last time!  :)

Try gdb
http://www.gnu.org/software/gdb/
0
 
evilrixSenior Software Engineer (Avast)Commented:
^^^ BTW: It's not an IDE it's a debugger -- what is wrong with me today :)
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> Is g++ a compliant compiler?
Complaint with the C++ standard? Truth is, very few are 100% compliant but gcc (especially from 4.x onwards) does a very good job of coming close. Certainly more so than Microsoft's compiler.
0
 
Infinity08Commented:
>> >> C code will be accepted by a compliant C++ compiler
>> Sorry to disagree -- MOST but not all C code will be accepted.

True - there's no 100% compatibility, mostly due to C++'s type safety. I should have been more precise and said "Good C code will be accepted by a compliant C++ compiler" ;)

In any case, C code should be very easy to "port" to a C++ compiler ... just watch the warnings and errors the compiler throws out, and add explicit casts etc. wherever needed.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.