【问题标题】:Memory allocation in C malloc()C malloc() 中的内存分配
【发布时间】:2020-12-14 20:50:48
【问题描述】:

我对这段代码的行为有点困惑,

#include <stdio.h>
#include <stdlib.h>

char* foo(){
   char* arr = (char*)malloc(sizeof(char)*100);
   return arr;
}

void foo1(char* myArr){
 char* arr = (char*)malloc(sizeof(char)*100);
 myArr = arr;
}

int main(){
  char* myArr;
  foo1(myArr);
  myArr[23] = 'a';
  printf("%c", myArr[23]);
  return (0);

}

当我调用myArr = foo() 时,它工作得很好,分配的内存地址的值将分配给myArr,并且我有一个没有错误的分配内存段。另一方面,当我调用函数foo1(myArr) 时,它必须将myArr 传递给函数,它是一个指向段的指针,所以这个指针的任何更改都会影响内存段,(例如,如果我想交换两个字符串值,我可以简单地交换指针),但我会得到一个segmentation fault error,为什么?因为 myArr 不是 main 函数中的 myArr 吗?这是真的吗?!!

【问题讨论】:

  • 阅读Modern C和你的C编译器(可能是GCC ...)和调试器(可能是GDB)的文档....学习的源代码以获得灵感githubgitlab 上的现有 开源项目。通过为其中一些做出贡献,您将学到很多东西。 Wirth GCC,使用所有警告和调试信息进行编译,所以gcc -Wall -Wextra -g
  • 如果你使用real编译器,它有一个静态代码检查器。 clang -analyze.. 但是您也可以简单地注意到您的论点缺少一层间接性以使您的东西起作用。
  • 当然要注意call stack,但请记住,在某些情况下优化编译器可能会在某些processor register 中添加automatic variable。更多信息,请阅读this draft报告
  • @Basile Starynkevitch,在阅读了本书的某些部分之后,您提到了(现代 C),我发现它真的很有趣,它对我了解 C 编程语言有很大帮助。非常感谢您介绍这本书。
  • @AliNaderiParizi:花点时间阅读this draft,如果有兴趣,请通过电子邮件与我联系basile@starynkevitch.net

标签: c memory segmentation-fault malloc


【解决方案1】:

C 中的参数是 always 按值调用 -- 参数获取调用者传递的内容的 副本 并且是一个新变量,因此如果函数更改参数的值不会影响传入的值。所以当你调用时

foo1(myArr);

myArr 的值不会改变,即使 foo1 为其分配了不同的值。

【讨论】:

    【解决方案2】:

    您调用两个不同的变量myArr,这可能会让您感到困惑。对foo1 中的myArr 的更改不会影响main 中的myArr,因为它们具有相同的名称。您将mainmyArr 的值传递给foo1,但没有返回任何内容。

    void foo1(char* myArr){
     char* arr = (char*)malloc(sizeof(char)*100);
     myArr = arr;
    }
    

    这在概念上与:

    void foo1(int j) {
        int q = 2;
        j = q;
    }
    

    正如foo1(3) 不会以某种方式将3 变成2foo1(myArr) 不会改变myArr 的值。 myArr 是一个指针并不会改变它的语义——C 是按值传递,句点。所以只有myArr的值被传递给函数。

      char* myArr;
      foo1(myArr);
    

    请注意,myArr 没有在此处分配值,因此您将 foo1 传递了一个指向任何特定对象的指针的值。 foo1 无法处理该值。

    你可能想要:

    void foo1(char** myArrPtr){
     char* arr = (char*)malloc(sizeof(char)*100);
     *myArrPtr = arr;
    }
    

     char* myArr;
     foo1(&myArr);
    

    这样,函数得到一个指向myArr的指针,然后修改指针指向的东西,即main中的myArr

    【讨论】:

    • 所以如果我想解决这个问题,我必须将void foo1(char* myArr) 更改为void foo1(char** myArr),并且在主函数中,我必须像这样foo1(&amp;myArr) 调用foo1,这样就可以解决问题.谢谢。
    • @AliNaderiParizi 没错。这样,您将传递一个指向 myArr 的指针,而不是它的(未指定且无意义的)值。
    • 而且,函数中分配的内存一直保留在那里,永远不会被释放。这是memory lack
    • @AliNaderiParizi 在这种情况下,foo1 的调用者通常会负责free 处理完内存。但是这段代码只是为了展示如何正确使用指针,它不是真实的代码。
    猜你喜欢
    • 1970-01-01
    • 2015-02-11
    • 2012-10-10
    • 2012-12-26
    • 2013-02-23
    • 2020-11-01
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    相关资源
    最近更新 更多