Thread: returning a string array from a function

  1. #1
    UK2
    Join Date
    Sep 2003
    Posts
    112

    returning a string array from a function

    Hello,

    I have a short example of a C library that I have coded below along with the header. I am calling this function from a C++ client app.

    Some of the warning I get are as follows. This normally gives me a segmentation stack run time error. So I guess some about memory not been allocated being assigned to null address.

    warning: return from incompatible pointer type
    warning: function returns address of local variable

    I have tried many different ways to do this. As you can see from my commenting out pieces of code.

    However, I can return pointer without any problems. However, my code needs to return a string array. i.e. char msgTest[] = "Hello how are you";

    Can any one offer any advice on this?

    Many thanks for any suggestions.

    Code:
    //C library code
    //Header cHeader.h
    #ifdef __cplusplus 
    extern "C"
    {
    #endif
    	char* returnMessage(char *message);
    #ifdef __cplusplus
    }
    #endif
    
    //Implementation cDriver.c
    char* returnMessage(char *message)
    {
    	printf("Message: %s\n", message);
    	
    	char *msg = NULL;
    // 	//msg = message;
    // 	printf("msg = message: %s\n", msg);
    // 	//strcpy(msg, message);
    // 	printf("strcpy(msg, message): %s\n", msg);
    	
    	char msgTest[] = "Hello how are you";
    	strcpy(msg, msgTest);
    	return &msgTest;
    }
    And the C++ code for calling the above function.
    Code:
    int main(int argc, char** argv)
    {
    	char *ptrTest = NULL;
    	char test[] = "Hello";
    	ptrTest = test;
    	char *ptrRtn = NULL;
    
    	ptrRtn = returnMessage(ptrTest);
    	cout << "PtrRtn: " << ptrRtn << endl;
    
            return 0;
    }

  2. #2
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Just remove the &:
    Code:
    return msgTest;

  3. #3
    UK2
    Join Date
    Sep 2003
    Posts
    112
    Hello,

    Code:
    return msgTest;
    I get the following warning: function returns address of local variable.

    I am not sure, but as this is a local variable the memory way not been available when the function returns? Just a guess.

    Thanks,

  4. #4
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    That is correct, you just described the problem. Therefore, what makes sense to fix that?
    Mainframe assembler programmer by trade. C coder when I can.

  5. #5
    UK2
    Join Date
    Sep 2003
    Posts
    112
    Hello,

    thanks for the reply,

    i have used malloc, which worked. Howerver, At which point do I free the memory? As I can't do it after I have returned, or after I have copied the contents?

    Code:
    char* returnMessage(char *message)
    {
    	printf("Message: &#37;s\n", message);
    	
    	char *msg = (char *) malloc(sizeof(char));
    	
    	char msgTest[] = "Hello how are you";
    	
    	strncpy(msg, msgTest, sizeof(msgTest));
    	
            //when to free the memory that has been allocated.
    	return msg;
    }
    I have noticed I get a stack dump.

    Many thanks,

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    you do nothing with the parameter (except printing it out)
    you allocate only 1 byte of memory, that is enough only for the empty string
    you cast malloc - that can be avoided in C
    you use strncpy in the disastrous way

    and answering your question - you should free memory in the calling function after you finished with the string returned
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    http://cpwiki.sourceforge.net/A_pointer_on_pointers
    A more common way of doing this is to take a buffer (read: pointer to a char array) and the size of that array and copy the data you want to return into that buffer. This avoids the need for malloc.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    UK2
    Join Date
    Sep 2003
    Posts
    112
    Hello,

    Thanks for your help. I have used the code below:
    Code:
    char* returnMessage(char *message)
    {
    	printf("Message: &#37;s\n", message); //Just testing the correct message is passed in, that is all.
    	
    	char msgTest[] = "Hello how are you";
    
    	char *msg = malloc(strlen(msgTest)); //Allocated the length of the string.
    
    	strncpy(msg, msgTest, strlen(msgTest)); //Used strlen instead of sizeof
    	
    	return msg;
    }
    Is the reason I am using strncpy in a bad way, because I previously used sizeof?

    Just a final question about freeing memory that has been allocated. As the function returnMessage allocated memory, how can I free that in the calling function, as it will not have scope?

    Many thanks,

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    1) Argument message is completely redundant because it is NEVER used.
    2) Allocating and returning a buffer like this is generally avoided, as I mentioned. Pass in a buffer and size and copy into the buffer.
    3) Sizeof evaluates the size of a type, but won't work on a pointer because the size where it points to is unknown. Why? I'll let you think on that.
    4) I suggest you read my linked article and think about the problem with freeing. The reason you're allocating on the heap is that it won't get freed until you explicitly choose to do so. You need to learn more about pointers.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    	char *msg = malloc(strlen(msgTest)); //Allocated the length of the string.
    
    	strncpy(msg, msgTest, strlen(msgTest)); //Used strlen instead of sizeof
    Those functions should definitely use strlen(msgTest)+1. This is to make sure the last zero-byte has space and gets copied, respectively.

    I would prefer to merge both calls to strlen() into one - store the result in a variable (e.g. len) and pass it to the relevant functions.

    You should also check for the sitatuon that malloc can not allocate memory (however unlikely that may seem), because otherwise you will write to address NULL, which is never correct - it just varies in badness from system to system.

    On the other hand, if you KNOW that you have allocated sufficient memory, why use strncpy() - it's not like the string you are copying is of unknown size - and if you insist on using strncpy(), then make sure you stuff a zero (nul, null-character or whatever you want to call it) at the end of the string, since if the string IS too long, the last byte written will

    I'm not entirely sure if sizeof(msgTest) is wrong here - I don't think so, as such. Of course, if the string is NOT an array, or it's a passed in array, then it will go wrong, so strlen is, from that perspective, a better solution.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Registered User
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217
    Best to do it like this:

    Code:
    char* ReturnMessage(char* out, size_t outSize)
    {
      char msgTest[] = "Hello how are you";
      strncpy(out, msgTest, outSize);
      return out;
    }
    
    int main(int argc, char* argv[])
    {
      char message[1024];
      ReturnMessage(message, sizeof(message));
      return 0;
    }

  12. #12
    UK2
    Join Date
    Sep 2003
    Posts
    112
    Hello,

    3) Sizeof evaluates the size of a type, but won't work on a pointer because the size where it points to is unknown. Why? I'll let you think on that.
    My best answer, as the pointer will only point to the first character in an array.

    When freeing memory I have freed the memory in the calling function. As below.
    Code:
    int main(int argc, char** argv)
    {
    	char *ptrTest = NULL;
    	char test[] = "Hello";
    	ptrTest = test;
    	char *ptrRtn = NULL;
    
    	ptrRtn = returnMessage(ptrTest);
    	cout << "PtrRtn: " << ptrRtn << endl;
            
            free(ptrRtn); //Freeing the memory that was allocated in the returnMessage function.
            return 0;
    }
    Any corrections please advise,

    Thanks,

  13. #13
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    cout <<
    this is C++ not C
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  14. #14
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    sizeof does not evaluate the expression, so it doesn't matter what pointers point to in a sizeof expression.

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    int main(int argc, char** argv)
    {
    	char test[] = "Hello";
    	char *ptrRtn = NULL;
    
    	ptrRtn = returnMessage(test); // No need for a temporary pointer
    	cout << "PtrRtn: " << ptrRtn << endl;
            
            free(ptrRtn); //Freeing the memory that was allocated in the returnMessage function.
            return 0;
    }
    And then comes the question - are you using C or C++? Cout is C++, free is C.
    And again, as noted, this is not the way to go about it. 39ster showed you a better way.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 05-13-2011, 08:28 AM
  2. In over my head
    By Shelnutt2 in forum C Programming
    Replies: 1
    Last Post: 07-08-2008, 06:54 PM
  3. Compile Error that i dont understand
    By bobthebullet990 in forum C++ Programming
    Replies: 5
    Last Post: 05-05-2006, 09:19 AM
  4. Replies: 4
    Last Post: 03-03-2006, 02:11 AM
  5. Replies: 6
    Last Post: 10-21-2003, 09:57 PM