简体   繁体   English

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

[英]Segmentation Fault when retrieving value from pointer in another function

I'm a beginner with C and am running into the following problem: 我是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
}

I can retrieve and print the value of the pointer within the function I allocated the memory for it, but outside of this (in main), it gives segmentation fault. 我可以在为其分配内存的函数中检索和打印指针的值,但在此之外(在main中),它会给出分段错误。

The issue you are having is a little more fundamental to your use of pointers and what happens when you pass a pointer as an argument to a function. 您遇到的问题对于使用指针更为重要,以及将指针作为参数传递给函数时会发生什么。 When you pass a pointer to a function (just like any variable), the function receives a copy of that pointer (or variable). 当您将指针传递给函数时(就像任何变量一样),该函数会接收该指针(或变量)的副本 Meaning that when header is passed to myFunc , myFunc receives a copy of header as data (with its very own, and very different, address ): 这意味着当header传递给myFuncmyFunc会收到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
}

Output 产量

$ ./bin/myFunc1

 the address of header in main: 0x7ffd112e27b8

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

Note: how the address of header in in main is 0x7ffd112e27b8 , but when you allocate memory for data in myFunc , you are assigning the starting address for the new block of memory to a pointer at 0x7ffd112e2798 . 注意: mainheader的地址如何是0x7ffd112e27b8 ,但是当你为myFunc data分配内存时,你将新的内存块的起始地址分配给0x7ffd112e2798的指针。 Nothing in main knows anything about memory address 0x7ffd112e2798 . main知道内存地址0x7ffd112e2798没有任何内容。

How Do We Fix it? 我们如何解决这个问题?

Just like you do every other time you wish to pass a variable to a function, update that variable, and have the changed value reflected back in the calling function ( main here) -- you pass the address of that variable to the function: 就像你每次都希望将变量传递给函数一样,更新该变量,并将更改后的值反映回调用函数(此处为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]);
}

Now that you have passed the address of header to myFunc as data , when you allocate memory for *data , you are allocating memory and returning the pointer to the same address for header in main . 现在您已将header地址作为data传递给myFunc ,当您为*data分配内存时,您正在分配内存并将指针返回到main header的相同地址。 Which allows: 这使得:

Output 产量

$ ./bin/myFunc2

 the address of header in main: 0x7ffdd72b1968

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

Making Use of the Return from myFunc 利用myFunc返回

You can also return the starting address for the new block of memory to main and accomplish the same thing, eg: 您还可以将新内存块的起始地址返回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;
}

Output 产量

$ ./bin/myFunc3

 the address of header in main: 0x7ffee22e3298

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

Now main knows about the address allocated to data in myFunc by virtue of assigning the return to header . 现在main通过将返回分配给header了解分配给myFunc data的地址。

In principle, you need to allocate the data before calling a function to work on it. 原则上,您需要在调用函数之前分配data以对其进行处理。 You did it the other way around, by allocating data inside the function, it is known inside the function itself but not in main . 你反过来做了,通过在函数内部分配data ,它在函数本身内部而不是在main已知。

In this particular case, you need to: 在这种特殊情况下,您需要:

  • Allocate the memory for data before calling myFunc() (inside that function itself you don't need to allocate the memory for data ): 在调用myFunc()之前为data分配内存(在该函数本身内部,您不需要为data分配内存):

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

myFunc(header);

  • Inside myFunc() , there is no need to allocate memory for the two pointers to char as you are using string literals: myFunc() ,当你使用字符串文字时,不需要为char的两个指针分配内存:

data[0] = "test";

However, it is possible to allocate memory for individual char pointer as well: 但是,也可以为单个char指针分配内存:

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

In that case, you can do strcpy or some other methods to set the content of data[0] and data[1] 在这种情况下,您可以使用strcpy或其他一些方法来设置data[0]data[1]


Alternatively, all allocation can be done inside myFunc() , but you need to change the prototype to return the proper pointer. 或者,所有分配都可以在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;
}

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

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