我正在编写一个程序,它接受一个路径列表(环境变量),分割路径并打印出来。在编译它时,我得到一个segfault以下是我在GDB上的输出:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400eb0 in dest (name=0x7fffffffbce0 "PATH") at executables.c:100
100     dest[i] = malloc(srclen+1);

在瓦尔格林:
==21574== 1 errors in context 2 of 3:
==21574== Use of uninitialised value of size 8
==21574==    at 0x400EB0: dest (executables.c:100)
==21574==    by 0x400B5B: main (main.c:9)

这是我的职责:
char** dest(char *name){
    int i=0;
    char *vp;
    const char s[2]=":";
    char *token;
    char **dest;
    name[strlen(name)-1]='\0';
    vp=getenv(name);
    if(vp == NULL){
        exit(1);
    }
    token =strtok(vp,s);
    while( token != NULL ){
        size_t srclen = strlen(token);
        dest[i] = malloc(srclen+1);
        strcpy(dest[i], token);
        token = strtok(NULL, s);
        i++;
    }
    dest[i]=NULL;
    return dest;
}

这是我的主题:
#include "executables.h"
int main(int argc, char **argv){
    char *path;
    char name[BUFSIZ];
    printf("enter name of environment variable:\n");
    fgets(name,BUFSIZ,stdin);
    char **p=dest(name);
    int j=0;
    while(p[j]!=NULL){
        printf("%s\n",p[j]);
        j++;
    }
    return(0);
}

最佳答案

使用strdup()。保存步骤(说明
“\0”也是)你必须在动手之前分配一些内存,以便使用这种方法。否则,您可能需要一个链接列表并分配数据包,而不是使用数组模式。当你说dest[i] = <ptr value>你正在索引一个未分配内存的偏移量,并存储一些东西,所以它是一个Sigvio。

#include <string.h>
#define MAXTOKENS  10000

char **get_dest(char *name) {
    // Since dest has to be exposed/persist beyond this function all
    // need dynamically allocate (malloc()) rather than stack allocate
    // of the form of: char *dest[MAXTOKENS].
    char *dest = malloc(MAXTOKENS * sizeof (char *));  // <--- need to allocate storage for the pointers
    char *vp;
    if ((vp = getenv(name)) == NULL)
        exit(-1); // -1 is err exit on UNIX, 0 is success

    int i = 0;
    char *token = strtok(vp, ":");
    while (token != NULL) {
        dest[i] = strdup(token); // <=== strdup()
        token = strtok(NULL, ":");
        i++;
    }

//  dest[i] = NULL;  // Why are you setting this to NULL after adding token?
    return dest;

}

最好是main()负责将以空结尾的字符串传递给get_dest()函数,因为main是finicky fgets()的处理位置一般来说,你想在当地做一些最有意义、最相关的事情。如果您曾经使用get_dest()函数并在fgets()未读取字符串的地方使用它,那么在那里重写终止符将是一个浪费的步骤。因此,通过在fgets()之前将char数组初始化为零,您不必担心将尾部字节设置为'\0'。
最后,让函数名dest与它返回的变量名dest同名可能不太好在某些情况下,程序中有多个同名符号可能会给您带来麻烦。
#include "executables.h"
int main(int argc, char **argv) {
    char *path;
    char name[BUFSIZ] = { 0 };  // You could initialize it to zero this way
    printf("enter name of environment variable:\n");
//  bzero(name, BUFSIZ); //... or you could initialize it to zero this way then
    fgets(name, BUFSIZ, stdin);
    char **p = get_dest(name);
    int j = 0;
    while(p[j] != NULL) {
        printf("%s\n", p[j]);
        j++;
        free(p[j]);  // like malloc(), strdup'd() strings must be free'd when done
    }
    free(p);
    return 0;
}

关于c - C程序中的段错误,malloc调用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41971159/

10-11 23:06
查看更多