C程序中的Segfault,malloc调用 [英] Segfault in C program, malloc call

查看:147
本文介绍了C程序中的Segfault,malloc调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing a program that takes a list of path ( environmental variable), splits the paths and prints it. When compiling it I get a segfault. The following is my output on GDB :

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

关于valgrind:

On valgrind:

==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)

这是我的函数:

This is my function:

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;
}

这是我的主要内容:

And this is my main:

#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值> 时,你会索引到未分配内存的偏移量并在那里存储某些内容,所以它是一个segvio。

Use strdup(). Saves steps (accounts for '\0' too). You have to allocate some memory before hand for the approach you're using. Otherwise you might want a linked list and allocate packets instead of using the array pattern. When you say dest[i] = <ptr value> you're indexing to an offset of unallocated memory and storing something there, so it's a segvio.

#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()需要传递适当的以null结尾的字符串到get_dest()函数,因为main是处理finicky fgets()的地方。一般而言,你想在本地做最有意义且最相关的事情。如果你曾经使用过get_dest()函数,并将它用在fgets()没有读取字符串的地方,那么在这里覆盖终止符只是一个浪费的步骤。因此,通过在fgets()之前将char数组初始化为零,您不必担心将尾随字节设置为'\ 0'。

It's better if main() takes care of passing a proper null-terminated string to the get_dest() function because main is where the finicky fgets() is handled. Generally you want to do things locally where it makes the most sense and is most relevant. If you ever took your get_dest() function and used it somewhere where the strings were not read by fgets() it would just be a wasted step to overwrite the terminator there. So by initializing the char array to zeroes before fgets() you don't have to worry about setting the trailing byte to '\0'.

最后可能不会很好让你的函数名dest与它返回dest的变量名相同。在某些情况下,程序中有多个相同名称的符号可能会导致您遇到麻烦。

And finally probably not good to have your function name dest the same name as the variable it returns dest. In some situations having multiple symbols in your program with the same name can get you into trouble.

#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程序中的Segfault,malloc调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆