繁体   English   中英

当写一个返回指针的 function 时,为什么要分配 memory 给我要返回的指针?

[英]When writing a function that returns pointer, why should I allocate memory to the pointer I'm going to return?

当谈到 memory 分配和指针时,我有点弱。 所以,我想了解为什么我必须将 memory 分配给函数中的指针,如下所示:

char *cstring(char c, int n)
{
int i = 0;
char * res;
res = malloc ((n+1)*sizeof(char));
while (i<n)
{
    res[i]=c;
    i++;
}
res[i] ='\0';
return res;
}

为什么以下无效?

char *cstring(char c, int n)
{
int i = 0;
char * res;
while (i<n)
{
    res[i]=c;
    i++;
}
res[i] ='\0';
return res;
}

我知道我应该(通常)将 memory 分配给指针,以便它们定义 memory。 但是,我想主要了解它与堆栈和堆内存的概念有什么关系! 提前致谢!

指针需要指向有效的 memory 位置,然后才能取消引用。

在您的第一个示例中, res指向分配的 memory 块,随后可以对其进行写入和读取。

在您的第二个示例中,当您尝试取消引用res时,它保持未初始化 这会导致未定义的行为 在这种情况下,最可能的结果是,它包含的任何垃圾值都不是有效的 memory 地址,因此当您尝试取消引用该无效地址时,您的程序将崩溃。

您的代码的第二个版本声明了一个指针,但没有将其初始化为指向一个有效的 memory 地址。

然后,代码在循环期间取消引用该指针。 因此,在这种情况下,您的代码将访问未初始化的 memory。 请记住,数组索引只是解除引用的语法糖——因此您的代码访问 memory 是不应该的。


您的代码的第一个版本将指针初始化为实际指向某物,因此当您在循环期间取消引用它时,它可以工作。

当然,无论哪种情况,您都从 function 返回指针——它只是在第一个版本中指向有效的东西,而在第二个版本中它指向任何地方


这里的道德是始终初始化您的变量。 不这样做可能会导致代码中出现未定义的行为(即使它有时似乎可以工作)。 这里的一般建议是始终使用至少一些编译标志来编译您的代码。 例如在gcc / clang中,考虑-Wall -Werror -Wextra 此类选项通常适用于未初始化变量的简单情况。

此外, valgrind是 memory 分析的出色工具。 它可以在运行时轻松检测未初始化的 memory 的使用,以及 memory 泄漏。

如果你声明一个这样的变量,

int A = 5;

那么这意味着变量将在堆栈上。 当函数被调用时,它们的局部变量被压入堆栈。 主要的 function 也是一个例子。 因此,您不必手动分配 memory,您的编译器将在后台为您执行此操作,然后再调用您的主 function。 这也意味着如果您在执行 function 期间检查堆栈,您可以看到值 5。

有了这个,

int  A = 5;
int *PtrToA = &A;

指针将再次在堆栈上。 但是这一次,堆栈上的值只是显示了我们想要的实际 integer 值的 memory 地址。 它指向保存值 5 的 memory 块的地址。由于此处 A 保存在堆栈中,因此指针将显示堆栈上的 memory 地址。 就像您问题中的情况一样,您可以动态分配 memory 。 但是您必须在阅读之前对其进行初始化。 因为当您请求分配 memory 时,您的操作系统会在程序堆中搜索有效的 memory 字段并为您保留该字段。 比它还给你它的地址并给你读写权限,所以你可以使用它。 但是其中的值不会包含您想要的。 当编译器在堆栈上分配时,初始值将再次取消设置。 如果你这样做,

char *res;
res[1] = 3;

变量 res 将在堆栈上,它将包含一些随机值。 所以访问它就是这样,

(rand())[1] = 3;

您可能会收到访问冲突错误,因为您可能无权写入该 memory 位置。

重要说明; 在您的 function 调用返回后,堆栈上的局部变量值不再有效。 所以要小心。 在 function 调用结束后不要取消引用它们。

综上所述; 如果要使用指针,请确保它指向有效的 memory 位置。 你可以自己分配或者让它指向另一个memory地址。

很简单:因为您没有为您写入的数据分配任何 memory。 在您的示例中,您定义了指针,您没有对其进行初始化,因此它将引用 memory 中的随机(或者更确切地说不可能预测)位置,然后您尝试写入此随机 memory 位置。

您在 5 行示例中有 2 个未定义的行为。 你的指针没有初始化,并且你没有分配任何有效的 memory 这个指针来引用。

编辑:

有效的

char *cstring(char c, int n)
{
    char * res;
    res = malloc ((n+1)*sizeof(char));
char *cstring(char c, int n)
{
    char * res;
    static char buff[somesize];
    res = buff;
char buff[somesize];
char *cstring(char c, int n)
{
    char * res;
    res = buff;

无效的

char *cstring(char c, int n)
{
    char * res;
    char buff[somesize];
    res = buff;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM