【问题标题】:How to realloc a memory? I keep getting segmentation fault如何重新分配内存?我不断收到分段错误
【发布时间】:2014-05-12 18:01:44
【问题描述】:

我一直在主函数中遇到段错误。我创建了一个指向我创建的结构的指针,并将它的引用传递给另一个分配和重新分配内存的函数。然后在主函数(最初定义的地方)中访问它会导致段错误。

这是我的测试代码:

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

typedef struct {
  char desc[20];
  int nr;
} Kap;

void read(Kap *k);

int main(void) {
  Kap *k = NULL;
  read(k);

  printf("__%s %d\n", k[4].desc, k[4].nr);
  return 0;
}

void read(Kap *k) {
  int size = 3;
  k = (Kap*) calloc(size, sizeof(Kap));

  k[0].nr = 1;
  k[1].nr = 2;
  k[2].nr = 3;

  strcpy(k[0].desc, "hello0");
  strcpy(k[1].desc, "hello1");
  strcpy(k[2].desc, "hello2");

  size *= 2;
  k = (Kap*) realloc(k, sizeof(Kap)*size);
  if(k == NULL) {
    printf("ERROR\n");
    exit(EXIT_FAILURE);
  }


  k[3].nr = 4;
  k[4].nr = 5;
  k[5].nr = 6;

  strcpy(k[3].desc, "hello3");
  strcpy(k[4].desc, "hello4");
  strcpy(k[5].desc, "hello5");
}

我做错了什么?

【问题讨论】:

  • 提示:尝试在 read() 之前和之后打印 main() 中 k 的值。价值观应该改变吧?但他们没有。
  • 使用格式"%p" 打印指针。不要忘记转换为 void* 或 char* 之前。
  • 请记住,C 中的每个函数都是按值传递的。这意味着,如果您将指针传递给它,该函数实际上会收到该指针的副本。在许多情况下,这是可以的,因为指针及其副本将指向同一个空间。在这种情况下,它不行,因为您希望 main 中的指针 k 在调用 read 后指向其他地方。但是read只能对k的副本进行操作。

标签: c segmentation-fault realloc pass-by-reference


【解决方案1】:

这是您遇到的问题的简化版本:

#include <stdio.h>

void func(int x)
{
    x = 10;
}

int main()
{
    int x = 5;
    printf("x = %d\n", x);
    func(x);
    printf("x = %d\n", x);
}

x 不变的原因与您的程序中k 不变的原因相同。一个简单的解决方法是:

Kap *read()
{
    Kap *k = calloc(...);
    ...
    k = realloc(k, ...);
    ...
    return k;
}

int main()
{
    Kap *k = read();
    ...
}

【讨论】:

  • 你们太棒了! :) 我不这么认为。这就是 realloc 返回 指针而不是改变它的原因。非常感谢!
  • @Ctwx 这是因为指针在 C 中的工作方式。对于 realloc 来更改指针,它需要一个不同的接口。它需要接受一个指向指针的指针。
【解决方案2】:

问题是您没有将指针传递回main()。尝试这样的事情:

Kap * read();

int main(void) {
  Kap *k = read();

  printf("__%s %d\n", k[4].desc, k[4].nr);
  return 0;
}

Kap * read() {
    ... everything else you're already doing ...
    return k;
}

您显示的代码将指针按值传递到read()。子例程可以使用该指针(尽管它有点无用,因为它的本地副本会立即更改),但是在 read() 中所做的更改不会返回给它的调用者。

我的建议是允许read() 重新发送新指针的一种方法,这可能是选择的正确方法。另一种方法是将read()s 签名更改为void read(Kap **);,它将接收指向指针的指针——允许它修改调用者的指针(由于通过引用传递)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    • 2017-11-21
    • 2014-04-25
    • 1970-01-01
    • 2020-12-27
    • 2020-11-04
    相关资源
    最近更新 更多