返回函数中的指针

dev*_*ium 2 c c++

以下代码是否合法?

char* randomMethod1() {
    char* ret = "hello";
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

还有这个?

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

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

    ret[9] = '\0';

    return ret;
}
Run Code Online (Sandbox Code Playgroud)

我会说第一个是合法的,因为你实际上正在做的是返回一个指向字符串文字的指针,我认为它是从程序的字符串表中加载的.但是,我会说第二个不是.我会在第二种方法中说你在堆栈上分配内存,一旦你离开函数,它可能被另一种方法使用,转向垃圾你要返回的指针.它真的有用吗?

编辑:好的,这是反汇编代码.任何人都可以解释我怎么能看到它被分配在堆上?

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              
Run Code Online (Sandbox Code Playgroud)

Meh*_*ari 17

两者都是合法的.在第二个中,您没有从堆栈中分配内存.您正在使用new它并从堆中分配内存.如果你没有释放第二种方法返回的指针delete,你就会有内存泄漏.

顺便说一句,堆栈分配的数组声明如下:

char x[10]; // note that there's no `new`.
Run Code Online (Sandbox Code Playgroud)

更新:

该行调用operator new从堆中分配内存并初始化对象.

00053700  call        operator new (511E0h) 
Run Code Online (Sandbox Code Playgroud)

  • 吞噬:是的.可以重载`operator new`来控制分配,但在正常情况下,它会. (5认同)
  • `"hello"` 是指向可执行文件的某些数据部分中的字符串的指针。它不会以任何方式复制到堆栈。仅将其地址复制到堆栈中。 (2认同)

sha*_*oth 8

事实上两者都是合法的.在第二种情况下,您在堆中分配内存,而不是在堆栈上.这一行:

00053700  call        operator new (511E0h)
Run Code Online (Sandbox Code Playgroud)

是一个operator new负责内存分配的调用.

堆栈上的分配如下:

char* randomMethod2() {
    char ret[10];
    ....
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

确实会导致未定义的行为.

但是请不要忘记,在第一种情况下,尝试通过返回的指针修改内存也会导致未定义的行为.在第二种情况下,调用者负责释放内存(调用delete[]).