在编写返回指针的函数时,为什么要为要返回的指针分配内存?

时间:2021-01-18 13:34:21

标签: c pointers dynamic-memory-allocation

在内存分配和指针方面我有点弱。 所以,我想了解为什么我必须为函数中的指针分配内存,如下所示:

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;
}

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

4 个答案:

答案 0 :(得分:3)

指针需要指向一个有效的内存位置才能被取消引用。

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

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

答案 1 :(得分:1)

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

然后,代码在循环中取消引用那个指针。因此,在这种情况下,您的代码将访问未初始化的内存。请记住,数组索引只是用于取消引用的语法糖 - 因此您的代码访问不应该访问的内存。


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

当然,无论哪种情况,您都会从函数中返回指针——只是在第一个版本中它指向有效的内容,而在第二个版本中它指向任何地方。 >


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

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

答案 2 :(得分:1)

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

int A = 5;

那么这意味着变量将在堆栈上。当函数被调用时,它们的局部变量被压入堆栈。 main 函数也是一个例子。所以你不必手动分配内存,你的编译器会在调用你的主函数之前在后台为你做这件事。这也意味着如果您在函数执行期间检查堆栈,您可以看到值 5。

有了这个,

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

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

char *res;
res[1] = 3;

变量 res 将在堆栈中,它将包含一些随机值。所以访问它就像那样,

(rand())[1] = 3;

您可能会收到访问冲突错误,因为您可能没有写入该内存位置的权限。

一个重要的注意事项;函数调用返回后,堆栈上的局部变量值不再有效。所以要小心。不要在函数调用结束后取消引用它们。

总结;如果要使用指针,请确保它指向有效的内存位置。你可以自己分配它或者让它指向另一个内存地址。

答案 3 :(得分:0)

简单:因为您没有为您写入的数据分配任何内存。在您的示例中,您定义了指针,但没有对其进行初始化,因此它将引用内存中的随机(或无法预测)位置,然后您尝试写入该随机内存位置。

您在 5 行示例中有 2 个未定义的行为。您的指针未初始化,并且您没有为此指针分配任何有效内存以供参考。

编辑:

有效

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;
相关问题