2

此代码获取从函数返回的值,创建并将其放入名为变量“b”的新地址空间中

    int main()
{
    int b;
    b = topkek();
    std::cout << &b;


};

int topkek()
 {
    int kek = 2;

    return kek;

 };

现在我明白了,因为变量 kek 在 topkek 方法中,我无法从 main() 方法访问它。使用 C++ 和指针,我想出了如何访问在方法内声明的变量,即使在方法终止后,看看这段代码。

int main()
{
    int * a;
    a = topkek();  //a is now pointing at kek

    std::cout << *a; //outputs 2, the value of kek.

    *a = 3;

    std::cout << *a; //output 3, changed the value of kek.

    std::cin >> *a;


};

int * topkek()
 {
int kek = 2;
    int* b = &kek;  //intializing pointer b to point to kek's address in stack

    return b; //returning pointer to kek

};

这种方法安全吗?编译器是否会阻止 kek 的地址空间稍后在代码中被覆盖,因为它仍然理解它正在被使用?

4

9 回答 9

4

这是未定义的行为:一旦函数完成,通过指针或引用访问其中的变量会使程序无效,并可能导致崩溃。

但是,当您“返回”堆栈时访问变量是完全有效的:

void assign(int* ptr) {
    *ptr = 1234;
}
int main() {
    int kek = 5;
    cout << kek << endl;
    assign(&kek);
    cout << kek << endl;
}

请注意如何assign访问在另一个函数中声明的局部变量的值。这是合法的,因为main在访问发生时还没有完成。

于 2013-08-12T14:29:24.623 回答
4

不,这不安全。函数完成执行后,您不再指向 a int,而只是指向内存中的某个随机位置。它的值可以是任何值,因为它可以在程序的其他地方进行修改。

于 2013-08-12T14:30:30.240 回答
3

当一个局部变量被“创建”时,编译器通过在堆栈[1]上给变量一些空间来做到这一点。只要您在该函数内,该空间就可用于变量。当函数返回时,空间被释放,可供其他函数使用。因此,b第二个代码中的地址返回一个指向内存的指针,该指针将在返回完成后立即释放。

尝试添加如下内容:

int foo()
{
     int x = 42;
     cout << "x = " << x << endl;
     return x;
}

foo在您调用 之后调用topkek,并且可以肯定kek(或指向kek)中的值会发生变化。

[1] 对于学究:是的,C++ 标准没有指定需要有一个堆栈,或者应该如何使用局部变量等等。但总的来说,在当今几乎所有可用的编译器中,这它是如何工作的。

于 2013-08-12T14:36:15.383 回答
3

绝对不安全。将导致未定义的行为。

于 2013-08-12T14:28:47.407 回答
2

这将是安全的:

int * topkek()
{
    static int kek = 2;
    int* b = &kek;  //intializing pointer b to point to kek's address in stack
    return b; //returning pointer to kek
};
于 2013-08-12T14:33:26.657 回答
2

退出函数范围时,本地分配的自动类型将自动释放。然后,您返回的指针将指向已释放的内存。访问此内存将导致undefined behaviour.

int* topkek() {
    int kek = 2; // Create a local int kek

    int* b = &kek;  // Declare pointer to kek

    return b; // Return pointer to local variable. <-- Never do this!
}; // kek is destroyed and the returned pointer points to deallocated memory.
于 2013-08-12T14:31:46.213 回答
1

首先,正如其他人所指出的,这绝对是不安全的。但是根据您的用法,我认为您实际上可能正在尝试定义一个对象。例如,此代码可能是您想要的:

struct topkek{
    int kek;
    int *operator()() {
        kek = 2;
        return &kek;
    }
};

int main()
{
    topkek mykek;

    int *a = mykek(); // sets mykek.kek to 2, returns pointer to kek

    std::cout << *a;
    *a = 3;
    std::cout << *a;
    std::cin >> *a;
};

这将使您kek以完全安全的方式干净地访问底层变量。您当然可以将任何您想要的代码放入该operator()方法中。

于 2013-08-12T14:59:50.887 回答
1

这是一个局部变量undefined behaviorkek它驻留的内存将在您退出后被释放topkek。它可能看起来有效,但由于它是未定义的,任何结果都可能发生,它可能随时中断,您不能依赖结果。

于 2013-08-12T14:29:51.580 回答
1

这是未定义的行为。从函数返回后,kek不再存在,返回的指针指向涅槃,指向kek曾经所在的位置。访问它会给出未定义的行为。未定义的行为意味着,任何事情都可能发生。您确实可以获得曾经存在的值,kek或者您的应用程序崩溃,或者您获得一些垃圾值,或者您的编译器认为适合在线为您订购比萨饼,请多加奶酪。

于 2013-08-12T14:31:53.543 回答