You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将字符串复制到不可访问内存?C语言argv赋值问题求助

问题分析与解决

核心问题

你的代码存在两个关键错误:

  1. 直接strcpy到未初始化指针:argv是通过malloc(MAXARGS*sizeof(char))分配的指针数组,但数组内的每个argv[argc]都是未初始化的野指针,直接调用strcpy会往随机内存地址写入数据,触发段错误。
  2. 悬空指针问题:若直接让argv[argc]=ptr,ptr指向的是buf2内部的内存区域,free(buf2)后该内存被系统回收,argv里的指针就变成悬空指针,后续访问会导致未定义行为。

解决方案

要让argv的内容在buf2释放后依然有效,必须为每个参数独立分配内存,将ptr指向的字符串复制到新内存中,而非直接复用buf2内的指针。

实现方式1:malloc+strcpy手动分配

对每个解析出的参数,先分配足够容纳字符串(含终止符\0)的内存,再复制内容:

while (ptr != NULL) {
    // 分配内存:字符串长度 + 1(存储'\0')
    argv[argc] = malloc(strlen(ptr) + 1);
    if (argv[argc] == NULL) {
        perror("malloc failed");
        exit(1);
    }
    strcpy(argv[argc], ptr);
    argc++;
    ptr = strtok(NULL, " ");
}

实现方式2:用strdup简化代码(POSIX标准)

strdup会自动完成内存分配与字符串复制,等价于malloc+strcpy,代码更简洁:

while (ptr != NULL) {
    argv[argc] = strdup(ptr);
    if (argv[argc] == NULL) {
        perror("strdup failed");
        exit(1);
    }
    argc++;
    ptr = strtok(NULL, " ");
}

注意内存回收

由于argv的每个元素都单独分配了内存,在eval函数中释放argv前,需要先逐个释放这些元素,避免内存泄漏:

void eval(char* cmdline)
{
    char** argv=malloc(MAXARGS*sizeof(char)); /* Argument list execve() */
    char buf[MAXLINE];   /* Holds modified command line */
    int bg;              /* Should the job run in bg or fg? */
    pid_t pid;           /* Process id */

    strcpy(buf, cmdline);
    bg = parseline(buf, argv);

    // 先释放每个参数的内存
    int i = 0;
    while (argv[i] != NULL) {
        free(argv[i]);
        i++;
    }
    // 再释放指针数组本身
    free(argv);
}

修改后的完整parseline函数

int parseline(char* buf, char** argv)
{
    int argc;            /* Number of args */
    int bg;              /* Background job? */
    char* buf2=malloc(MAXLINE * sizeof(char));
    while (*buf && (*buf == ' '))
        buf++;
    buf[strlen(buf) - 1] = ' ';/* Replace trailing '\n' with space */
    strcpy(buf2, buf);

    /* Build the argv list */
    argc = 0;
    char* ptr = strtok(buf2, " ");
    printf("ptr: %s\n", ptr);
    while (ptr != NULL) {
        // 用strdup分配内存并复制字符串
        argv[argc] = strdup(ptr);
        if (argv[argc] == NULL) {
            perror("strdup error");
            exit(EXIT_FAILURE);
        }
        argc++;
        ptr = strtok(NULL, " ");
    }
    argv[argc] = NULL;
    printf("0: %s\n", argv[0]);

    /* Ignore blank line */
    if (argc == 0)
        return 1;

    /* Should the job run in the background? */
    if ((bg = (*argv[argc - 1] == '&')) != 0) {
        free(argv[--argc]); // 释放&对应的内存
        argv[argc] = NULL;
    }
    free(buf2);
    printf("0: %s\n", argv[0]);
    if(argv[1]!=NULL)
        printf("1: %s\n", argv[1]);
    return bg;
}

内容的提问来源于stack exchange,提问作者newb hi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 12:01:46