为啥在将 malloc() 的指针分配给 char* 时会出现段错误?

Posted

技术标签:

【中文标题】为啥在将 malloc() 的指针分配给 char* 时会出现段错误?【英文标题】:Why am I getting a segfault when assigning a malloc()'d pointer to a char*?为什么在将 malloc() 的指针分配给 char* 时会出现段错误? 【发布时间】:2015-02-04 21:27:09 【问题描述】:

我有一个带有两个 char* 指针的结构:

typedef struct
    char* command;
    char* option;
 Command;

然后我有一个从套接字读取的函数,将数据分成两部分(命令和选项),然后填充一个结构以返回给调用者。但是,我有一次遇到了段错误,我不明白为什么。

这是我得到段错误信号的地方:

commandStruct->command = strdupa(cmd);

这是我的变量的声明:

Command* commandStruct = malloc(sizeof(Command));
char *cmd, *option;
int cmdLen, optLen;

让我感到困惑的是,这只是一个简单的任务,不应该这么难。我对 C 的细微差别非常不熟悉,因此经验丰富的程序员可能会明白这一点。任何帮助表示赞赏。

编辑:我已经调整了我的第一个 malloc,以便为指针腾出空间,但我仍然遇到问题。 Valgrind 提到我正在写 8 个坏字节,并且“地址 0x0 没有被堆栈、malloc 或(最近)释放”。为了更透明,我将在下面粘贴整个函数的副本,以防万一。

Command* getCommand(int cfd)

    Command* commandStruct = NULL; 
    char cmdStr[200];
    char *cmd = NULL, *option = NULL;
    int recieved, cmdLen, optLen;

    commandStruct = malloc(sizeof(Command));

    memset(cmdStr, '\0', sizeof(cmdStr));
    memset(commandStruct, 0, sizeof(Command));



    if(commandStruct == NULL)
    
        fatal("sir, you malloc'd a null pointer. Memory problems?.\n");
    

    if((recieved = recv(cfd, cmdStr, MAXLINE, 0)) == -1) errExit("recv");
    verbosePrint(opts.v, "recv'd %u bytes: %s\n", recieved, cmdStr);

    if(!strncmp(CMD_DIR, cmdStr, strlen(CMD_DIR)))
    
        cmd = CMD_DIR;
        option = NULL;
        verbosePrint(opts.v, "set cmd to: %s\n", cmd);
    
    else if(!strncmp(CMD_CHDIR, cmdStr, strlen(CMD_CHDIR)))
    
        cmd = CMD_CHDIR;
        option = &cmdStr[sizeof(CMD_CHDIR)];
        verbosePrint(opts.v, "set cmd to: %s\n", cmd);
        verbosePrint(opts.v, "set option to: %s\n", option);
    
    else if(!strncmp(CMD_PWD, cmdStr, strlen(CMD_PWD)))
    
        cmd = CMD_PWD;
        option = NULL;
        verbosePrint(opts.v, "set cmd to: %s\n", cmd);
    
    else if(!strncmp(CMD_PUT, cmdStr, strlen(CMD_PUT)))
    
        cmd = CMD_PUT;
        option = &cmdStr[sizeof(CMD_PUT)];
        verbosePrint(opts.v, "set cmd to: %s\n", cmd);
        verbosePrint(opts.v, "set option to: %s\n", option);
    
    else if(!strncmp(CMD_GET, cmdStr, strlen(CMD_GET)))
    
        cmd = CMD_GET;
        option = &cmdStr[sizeof(CMD_GET)];
        verbosePrint(opts.v, "set cmd to: %s\n", cmd);
        verbosePrint(opts.v, "set option to: %s\n", option);
    

    commandStruct->command = strdupa(cmd);

    if(option != NULL)
    
        commandStruct->option = strdupa(option);        
    

    return commandStruct;

【问题讨论】:

您需要为字符串的空终止符分配另一个字节。 使用-Wall 编译。不要投射malloc,它会隐藏错误:***.com/a/605858/19410 我不知道 malloc,谢谢你的提示。而且我确实使用 -Wall 进行编译,我没有收到任何错误。 要获得诸如“我为什么会遇到 valgrind 错误”之类的问题的帮助,请发帖 MCVE 关于这一行: if((recieved = recv(cfd, cmdStr, MAXLINE, 0)) == -1) errExit("recv"); cmdStr 设置为 200 字节,而不是 MAXLINE 字节。建议更新 cmdStr 的声明以使用 MAXLINE 【参考方案1】:

你的代码

Command* commandStruct = (Command*) malloc(sizeof(commandStruct));

正在分配空间。您分配了足够的空间来存储指向命令的指针而不是命令本身。

尝试将其替换为

Command* commandStruct = malloc(sizeof(*commandStruct));

这应该给你足够的空间。您还在为要存储的字符串分配空间。考虑改用 strdup。

希望这会有所帮助!

【讨论】:

不应该是Command* commandStruct = (Command*) malloc(sizeof(Command)); 以便它实际分配存储结构中所有内容所需的空间吗?您不能只为指针地址分配空间,那是行不通的。如果 Command 是一个类,你会调用 Command* commandStruct = new Command(); @MasterHD 我同意了你的建议——看起来任何一种都可行,但你的方式似乎更容易阅读 @templatetypedef 我已经尝试了您的两个建议,但我仍然遇到问题。您还有其他建议吗?感谢您迄今为止的帮助! @MasterHD 也可以。我个人喜欢 *commandStruct 技巧,因为即使变量的类型发生变化,它也可以工作,但两者都可以。此外,新命令在 C++ 中有效,但这是一个纯 C 问题。 :-) 结果,没有 new 关键字,也没有要运行的构造函数。 Downvoter - 你能告诉我我能做些什么来改善这个答案吗?我不确定它有什么问题。

以上是关于为啥在将 malloc() 的指针分配给 char* 时会出现段错误?的主要内容,如果未能解决你的问题,请参考以下文章

双指针将 char 数组值分配给 char 数组,结构使用 char 指针

为啥允许将字符串文字分配给 C++ 中 char * 类型的指针 [重复]

C语言如何给指针分配内存?

t=(char*)malloc(n*sizeof(char))的含义?

【50分】动态申请指针数组 ptr = malloc(sizeof(char *) * n);这申请了多大的内存?

为啥 malloc 返回一个指针?指针有啥用?