Microsoft – Visual C++ :- Compilation – Warning – warning C4172: returning address of local variable or temporary

Background

Ran into a compiler warning while compiling a simple C application.

Error

Error Text


warning C4172: returning address of local variable or temporary: type

Error Image

image_C1472_01_20191230_0803AM

Research

StackOverflow

warning: function returns address of local variable [enabled by default] [duplicate]

Link

https://stackoverflow.com/questions/17312336/warning-function-returns-address-of-local-variable-enabled-by-default  ( Link )

Code

Here is the cited code :-

Image

image_code_20191230_0827AM

Text


#include <string.h>
#include <stdio.h>
#include <stdlib.h>

char *chktype(char *Buffer, int Size)
{
   char *strng = "Content-Type: ";
   int sz;
   char *found = strstr (Buffer, strng);
   char *found1 = strstr(found, "\r\n");
   sz=strlen(found)-strlen(found1);
   char type[sz];
   strncpy(type, found1, sz-1);

   return(type);
}

void main(){

   char *buffer = "HTTP/1.1 200 OK\r\nDate: Tue, 25 Jun 2013 16:27:16
   GMT\r\nExpires: -1\r\nCache-Control: private,
   max-age=0\r\nContent-Type: text/html;
   charset=UTF-8\r\nContent-Encoding: gzip\r\nServer:
   gws\r\nX-XSS-Protection: 1; mode=block\r\nX-Frame-Options:
   SAMEORIGIN\r\nTransfer-Encoding: chunked\r\n\r\n";

   char *extension = chktype (buffer, sizeof(buffer));
   printf("%s\r\n", extension);
}

Question

This yields:


warning: function returns address of local variable [enabled by default]

…and i can’t figure out what is wrong here. When I run it, I expect the output to be text/html; charset=UTF-8 but its gibberish.

What does the warning mean exactly?

Answers

  1. Nobilis
    • Jun 26 ’13 at 5:47
      • You shouldn’t return local arrays from a function. One way as shown is to declare them static which will make them persist for the entire duration of the execution. The other is to allocate them using malloc.
        Nobilis Jun 26 ’13 at 5:47
  2. user529758
    • Jun 26 ’13 at 5:48
      • What do you even expect? Your code is a terrible mess, no one can read it, I’m sure even you can’t. Format it. –
        user529758 Jun 26 ’13 at 5:48
    • Jun 26 ’13 at 5:55
      • Also, rolled back to v1. No-one wants those ??s. We have enuf of’em already.
        user529758 Jun 26 ’13 at 5:55
  3. Cody Grey
    • Jun 26 ’13 at 5:50
      • The chktype function allocates memory for an automatic variable on the stack, and then returns the address of this variable (i.e., a pointer to this variable).The problem is that variables allocated on the stack are automatically destroyed whenever they go out of scope (i.e., control passes outside of the curly braces that define the function).

        This means that you’re essentially returning a pointer to an invalid memory location, which is bad news. In C-speak, it’s undefined behavior. In practical speak, it results in bad output or perhaps even a crash.

      • The correct way to return a char* from a function is to allocate new memory from the heap using the malloc (or calloc) function. That means that the caller of the function is going to be responsible for freeing the memory used by the returned value, otherwise your program will leak memory.
        (Always put this requirement into the documentation for your function! Even if “documentation” means a comment above the declaration.)
    •  Cody Gray♦ Jun 28 ’13 at 0:00 
      • @aDiAdam Yes, use the strncpy function like you did before. Start copying at the 18th character. You’ll get a new string that does not have the first 17 characters in the original. You can’t remove them in-place in C. String handling is a pain in the butt in low-level languages, that’s why people use C++ that gives you a built-in string class.
  4. Karthik T
    • Jun 26 ’13 at 5:46
      • Quick/Hacky answer(?):Make
        char type[sz];
        into
        static char type[sz];

        Long answer: The error is pretty clear, you are returning the address of a variable that is going to be destroyed soon as the function returns. There are a couple of ways to get around this.

        One easy way is to make type static, this would fix things, by making the type variable have a lifetime of the program, but this will mean that you cannot call it twice in a row, you need to print or copy the result before calling again.

        The other way, is to allocate memory for a char array within your function and hope that you remember to free it once you are done with it. If you don’t you will have a memory leak. This does not suffer from the above disadvantage.

      • i think that won’t be possible as i am using a variable length for the array, no?? – aDi Adam Jun 26 ’13 at 15:47
      • @aDiAdam ah yes I did not notice that.. you are right. – Karthik T Jun 26 ’13 at 23:27

 

Remediation

Outline

  1. Allocate Memory inside function using malloc
    • In Function
      • Allocate Memory
      • Return pointer to allocated memory
    • In calling function
      • Free Allocated Memory
  2. Add static to variable declaration
  3. Declare memory outside function
    • Calling Function
      • Declare variable
      • Pass variable by function
    • In function
      • Allocate Memory and set pointer to allocated memory
    • Calling Function
      • Use allocated memory
      • Free Memory

Code – Original Code


#include <string.h>
#include <stdio.h>
#include <stdlib.h>

char *chktype(char *Buffer, int Size)
{
   char *strng = "Content-Type: ";
   int sz;
   char *found = strstr (Buffer, strng);
   char *found1 = strstr(found, "\r\n");
   sz=strlen(found)-strlen(found1);
   char type[sz];
   strncpy(type, found1, sz-1);

   return(type);
}

void main(){

   char *buffer = "HTTP/1.1 200 OK\r\nDate: Tue, 25 Jun 2013 16:27:16
   GMT\r\nExpires: -1\r\nCache-Control: private,
   max-age=0\r\nContent-Type: text/html;
   charset=UTF-8\r\nContent-Encoding: gzip\r\nServer:
   gws\r\nX-XSS-Protection: 1; mode=block\r\nX-Frame-Options:
   SAMEORIGIN\r\nTransfer-Encoding: chunked\r\n\r\n";

   char *extension = chktype (buffer, sizeof(buffer));
   printf("%s\r\n", extension);
}

Choice – Malloc


char *chktypeUsingMalloc
(
      char *Buffer
    , int Size
)
{

    const char *strng = "Content-Type: ";

    int sz;
    char *found = (char *) strstr (Buffer, strng);
    char *found1 = (char *) strstr(found, "\r\n");
    sz=strlen(found)-strlen(found1);

    char *type = NULL;

    int iLength = 0;
    int iSize =0;

    /*
        Get length of string that we will be allocating
    */
    iLength = sz;

    printf
    (
          "\t allocating %d for char datatype \r\n"
        , iLength
    );

    /*
        Memory Block is
            sizeof data structure (size)
            times
            length of string
    */
    iSize = sizeof(char)
                    * ( iLength)
                ;                   

    /*
        Allocate Object
    */
    type = ( char * )
                malloc
                (
                    iSize
                );

    /*
        reset object (type)
    */
    memset(type, '\0', iSize);  

    /*
        copy data in found1 to type - size is sz-1
    */
    strncpy(type, found1, sz-1);

    return(type);
}

Choice – Static


char *chktypeUsingStatic
(
      char *Buffer
    , int Size
)
{

    // This pointer variable is allocated on the stack, but that's okay because
    // it's a pointer to a string literal, which are always constant.
    // (Technically, you should add the "const" qualifier to the declaration.)
    const char *strng = "Content-Type: ";

    int sz;
    char *found = (char *) strstr (Buffer, strng);
    char *found1 = (char *) strstr(found, "\r\n");
    sz=strlen(found)-strlen(found1);

    // Like all the above variables, the one is also allocated on the stack.
    // But it's the source of your problem here, because it's the one that
    // you are returning at the end of the function.
    // Problem is, it goes away at the end of the function!

    //error C2057: expected constant expression
    //error C2466: cannot allocate an array of constant size 0
    //error C2133: 'type': unknown size

    //char type[sz];
    //static char type[sz];
    static char type[4000];

    int iSize = 4000;

    memset(type, '\0', iSize);  

    strncpy(type, found1, sz-1);

    type[sz] = '\0';

    return(type);
}

Choice – Pass Variable By Reference

void chktypeUsingReferenceVariable
(
      char *Buffer
    , int  Size
    , char *type
)
{
    // This pointer variable is allocated on the stack, but that's okay because
    // it's a pointer to a string literal, which are always constant.
    // (Technically, you should add the "const" qualifier to the declaration.)
    const char *strng = "Content-Type: ";

    int sz;
    char *found = (char *) strstr (Buffer, strng);
    char *found1 = (char *) strstr(found, "\r\n");
    sz=strlen(found)-strlen(found1);

    strncpy(type, found1, sz-1);

    type[sz] = '\0';

}

Output

Output – Original

Images

Image – 01

output-original-01-20191230-1116AM

Image – 02

output-original-02-20191230-1117AM

Image – 03

output-original-03-20191230-1119AM

Output – Malloc

Images

Image – 01

output-malloc-01-20191230-1120AM.PNG

Output – Static

Images

Image – 01

output-static-01-20191230-1121AM.PNG

 

Output – Pass By Ref

Images

Image – 01

output-passByRef-01-20191230-1122AM.PNG

 

Compare Options

Here is a quick comparison of the options :-

  1. Allocated Memory
    • In called function, use malloc
      • In Malloc, size can match need
    • In called function, use static
      • Static – Variable Length
        • Original
          • static char type[sz];
        • Suggested
          • static char type [sz]
            • Error
              • error C2057: expected constant expression
              • error C2466: cannot allocate an array of constant size 0
              • error C2133: ‘type_2’: unknown size
        • Revised
          • static char type[4000];
          • Please issue size greater than what you need

Source Code Control

Github

  1. Source File
    Link

 

Dedicated

Dedicated to Cody Gray.

Cody Gray

https://stackoverflow.com/users/366904/cody-gray ( Link )

answer_codyGrey_C1472_01_20191230_0840AM

 

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s