从另一个函数中的指针检索值时出现分段错误

时间:2015-11-14 22:52:20

标签: c pointers

我是C的初学者,遇到了以下问题:

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

void myFunc(char **data);

int main() {
    char **header;
    myFunc(header);
    printf("[In main] %s\n", header[1]); // This gives segmentation fault
    return 0;
}

void myFunc(char **data) {
    data = (char **)malloc(2 * sizeof(char *));
    data[0] = "test";
    data[1] = "test 2";
    printf("[In myFunc] %s\n", data[1]); // This works just fine
}

我可以在为其分配内存的函数中检索和打印指针的值,但在此之外(在main中),它会给出分段错误。

2 个答案:

答案 0 :(得分:3)

您遇到的问题对于指针的使用更为重要,以及将指针作为参数传递给函数时会发生什么。当您将指针传递给函数(就像任何变量一样)时,该函数会接收该指针(或变量)的副本。这意味着当header传递给myFunc时,myFunc会收到header作为data的副本(有自己的,非常不同的,解决):

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

void myFunc(char **data);

int main() {
    char **header;
    printf ("\n the address of header in main: %p\n", &header);
    myFunc(header);
    printf("[In main] %s\n", header[1]); // This gives segmentation fault
    return 0;
}

void myFunc(char **data) {
    data = malloc(2 * sizeof(char *));
    printf ("\n the address of data in myFunc: %p\n", &data);
    data[0] = "test";
    data[1] = "test 2";
    printf("[In myFunc] %s\n", data[1]); // This works just fine
}

<强>输出

$ ./bin/myFunc1

 the address of header in main: 0x7ffd112e27b8

 the address of data in myFunc: 0x7ffd112e2798
[In myFunc] test 2
Segmentation fault

注意: headermain的地址如何0x7ffd112e27b8,但在data中为myFunc分配内存时您将新内存块的起始地址分配给0x7ffd112e2798处的指针。 main中的任何内容都不知道内存地址0x7ffd112e2798

我们如何修复它?

就像你每次都希望将变量传递给函数一样,更新该变量,并将更改后的值反映回调用函数(main这里) - 你传递 该函数变量的地址:

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

void myFunc(char ***data);

int main() {
    char **header;
    printf ("\n the address of header in main: %p\n", &header);
    myFunc(&header);  /* passing address of header to myFunc */
    printf("[In main] %s\n", header[1]);
    return 0;
}

void myFunc(char ***data) {
    *data = malloc(2 * sizeof(char *));
    printf ("\n the address of data in myFunc: %p\n", data);
    (*data)[0] = "test";
    (*data)[1] = "test 2";
    printf("[In myFunc] %s\n", (*data)[1]);
}

现在您已将 header地址传递给myFunc data,当您为*data分配内存时,您正在分配内存并将指针返回到headermain的同一地址。这允许:

<强>输出

$ ./bin/myFunc2

 the address of header in main: 0x7ffdd72b1968

 the address of data in myFunc: 0x7ffdd72b1968
[In myFunc] test 2
[In main] test 2

使用myFunc

的回报

你也可以返回并完成同样的事情,例如:

main

<强>输出

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

char **myFunc(char **data);

int main() {
    char **header;
    printf ("\n the address of header in main: %p\n", &header);
    header = myFunc(header);
    printf("[In main] %s\n", header[1]); // This works fine too
    return 0;
}

char **myFunc(char **data) {
    data = malloc(2 * sizeof(char *));
    printf ("\n the address of data in myFunc: %p\n", &data);
    data[0] = "test";
    data[1] = "test 2";
    printf("[In myFunc] %s\n", data[1]); // This works just fine
    return data;
}

现在$ ./bin/myFunc3 the address of header in main: 0x7ffee22e3298 the address of data in myFunc: 0x7ffee22e3278 [In myFunc] test 2 [In main] test 2 通过将回复分配给main,了解分配给datamyFunc的地址。

答案 1 :(得分:1)

原则上,您需要在调用函数之前分配data以进行处理。你反过来做了,通过在函数内部分配data,它在函数本身内部已知,但在main中却不知道。

在这种特殊情况下,您需要:

  • 在调用data之前为myFunc()分配内存(在该函数内部,您不需要为data分配内存):

header = (char **)malloc(2 * sizeof(char *));

myFunc(header);

  • myFunc()内部,当你使用字符串文字时,不需要为char的两个指针分配内存:

data[0] = "test";

但是,可能也为单个char指针分配内存:

data[0] = (char *)malloc(15 * sizeof(char));

在这种情况下,您可以执行strcpy或其他一些方法来设置data[0]data[1]的内容

或者,所有分配都可以在myFunc()内完成,但您需要更改原型以返回正确的指针。

char** myFunc() {
    char **data = (char **)malloc(2 * sizeof(char *));
    data[0] = "test";
    data[1] = "test 2";
    printf("[In myFunc] %s\n", data[1]);

    return data;
}

int main() {
    char **header;
    header = myFunc();
    printf("[In main] %s\n", header[1]);
    return 0;
}