Returned pointers in functions

Is the following code legal?

char* randomMethod1() {
    char* ret = "hello";
    return ret;
}

      

and this one?

char* randomMethod2() {
    char* ret = new char[10];

    for (int i = 0; i < 9; ++i) {
        ret[i] = (char)(65 + i);
    }

    ret[9] = '\0';

    return ret;
}

      

I would say the former is legal, as what you are actually doing is returning a pointer to a string literal, which I believe is being loaded from the program's string table. However, I would say the second is not. I would say that in the second method, you allocate memory on the stack, which, once you leave this function, can be used by another method, turning to garbage the pointer you are returning. How it works?

edit: Ok, here's the parsed code. Can anyone please explain to me how I can see it being allocated on the heap?

char* randomMethod2() {
000536E0  push        ebp  
000536E1  mov         ebp,esp 
000536E3  sub         esp,0E4h 
000536E9  push        ebx  
000536EA  push        esi  
000536EB  push        edi  
000536EC  lea         edi,[ebp-0E4h] 
000536F2  mov         ecx,39h 
000536F7  mov         eax,0CCCCCCCCh 
000536FC  rep stos    dword ptr es:[edi] 
    char* ret = new char[10];
000536FE  push        0Ah  
00053700  call        operator new (511E0h) 
00053705  add         esp,4 
00053708  mov         dword ptr [ebp-0E0h],eax 
0005370E  mov         eax,dword ptr [ebp-0E0h] 
00053714  mov         dword ptr [ret],eax 

    for (int i = 0; i < 9; ++i) {
00053717  mov         dword ptr [i],0 
0005371E  jmp         randomMethod2+49h (53729h) 
00053720  mov         eax,dword ptr [i] 
00053723  add         eax,1 
00053726  mov         dword ptr [i],eax 
00053729  cmp         dword ptr [i],9 
0005372D  jge         randomMethod2+5Fh (5373Fh) 
        ret[i] = (char)(65 + i);
0005372F  mov         eax,dword ptr [i] 
00053732  add         eax,41h 
00053735  mov         ecx,dword ptr [ret] 
00053738  add         ecx,dword ptr [i] 
0005373B  mov         byte ptr [ecx],al 
    }
0005373D  jmp         randomMethod2+40h (53720h) 

    ret[9] = '\0';
0005373F  mov         eax,dword ptr [ret] 
00053742  mov         byte ptr [eax+9],0 

    return ret;
00053746  mov         eax,dword ptr [ret] 
}
00053749  pop         edi  
0005374A  pop         esi  
0005374B  pop         ebx  
0005374C  add         esp,0E4h 
00053752  cmp         ebp,esp 
00053754  call        @ILT+320(__RTC_CheckEsp) (51145h) 
00053759  mov         esp,ebp 
0005375B  pop         ebp  
0005375C  ret              

      

+2


source to share


6 answers


Both are legal. In the second, you don't allocate memory from the stack. You are using new

and allocating memory from the heap. If you do not release the pointer returned from the second method using delete

, you will have a memory leak .

By the way, stack allocated arrays are declared like this:

char x[10]; // note that there no `new`.

      



Update:

This line calls operator new

, which allocates memory from the heap and initializes the object.

00053700  call        operator new (511E0h) 

      

+17


source


In fact, both are legal. In the second case, you are allocating memory on the heap, not on the stack. This line:

00053700  call        operator new (511E0h)

      

- the call operator new

that is responsible for memory allocation.

Stack allocation:



char* randomMethod2() {
    char ret[10];
    ....
    return ret;
}

      

will indeed result in undefined behavior.

However, don't forget that in the first case, trying to modify memory via the returned pointer will also cause undefined behavior. And in the second case, the caller is responsible for freeing memory (calling delete[]

).

+8


source


I think both are legal! The memory allocated by the new one is valid until we explicitly name the kernel or the program itself dies!

+3


source


With a fairly modern compiler, one should not compile first (or at least give a warning), then the fixed version is:

const char* randomMethod1() {
    const char* ret = "hello";
    return ret;
}

      

Since "hello" is a constant (in a static initialization space), it makes sense to use the address (but read-only). The second example is completely legal: you can pass (and use!) A pointer allocated with a new one as long as it is not called on it delete

. In this case, think about what you need to use delete []

(with the parenthesis operators when you allocated the array)

+3


source


Both assign variables on the heap, so when you return control from the function, both pointers will be alive.

In the second function

00053700 operator call new (511E0h)

calls new to allocate memory space.

The second would be illegal if you free ret using delete [] ret before returning the control;

To allocate a variable on the heap, you need to write: int ret [10]; now you cannot return a ret pointer because it will be destroyed at the end of the function.

0


source


Both are legal. But, in my opinion, the former can lead to head scratches. And semantically this is very different from the second.

The first

It is a string literal and it will survive outside the function and last the entire duration of the program, so it is declared on the heap.

My initial reaction to the first method was wrong. I thought it was declared on the stack as it is a local variable, but not precise. Since it is a string literal, this value is stored on the heap. However, the pointer that you created and return from this function is on the stack.

Second

The second declares memory on the heap via new, but you must definitely free it later using delete to avoid a memory leak. Memory is invalid after calling free.

Yes, every call to a new one allocates memory on the heap, not the stack.

Edit: Updated based on Pete's comment below and this question .

-2


source







All Articles