【问题标题】:Dynamic sized string in CC中的动态大小的字符串
【发布时间】:2013-01-13 15:58:57
【问题描述】:

我有以下代码并编辑我将在我正在创建的程序中处理的“路径”的字符串。

我的问题是我的代码有效,但我不知道为什么或更清楚我不明白为什么strcat 允许将src 附加到dest。由于一切都使用动态字符串,我不应该realloc dest。但是当我尝试这样做时,realloc 失败了

#include <stdio.h>
#include <string.h>

    int main(int argc, char** argv) {
        char *src = argv[1];
        char *dest = argv[2];
        char *d_basedir;
        int s_length = strlen(src);

        printf("dest starts as %s: length %zu\n", dest, strlen(dest));
        printf("src starts as %s: length %zd\n", src, strlen(src));

        if(!(src[s_length - 1] == '/')) {
            if((d_basedir = strrchr(src, '/')+1) != NULL) {
                printf("basedir is %s\n", d_basedir);
                strcat(dest, d_basedir);
                printf("dest changed to %s: length %zd\n", dest, strlen(dest));
            }
        }

        printf("dest ends as %s: length %zd\n", dest, strlen(dest));

        return 0;
    }

【问题讨论】:

  • 您不能通过realloc() 获得不是从malloc()(或其表亲)那里获得的东西。

标签: c string dynamic realloc strcat


【解决方案1】:

托管环境为您提供argv[] 数组,但您没有分配此内存,因此您不应尝试重新分配它。您根本不应该真正修改argv[]。如果要进行修改,请先复制字符串(使用malloc 等),然后至少可以确定是否有足够的空间,或者在连接之前是否需要使用realloc

【讨论】:

  • 修改argv[2]字符串的元素是完美定义的,但是写过去这些元素是未定义的。
  • 已定义但并不理想,尤其是在这种情况下。
  • 第一个 printf 给出了 argv[2] 的长度,即 dest 的确切长度。所以这不意味着最后有一个空字符并且附加到它应该失败
  • @johnsoga:您只能安全地假设argv[2] 的字符数与strlen() 所说的一样多,再加上一个(用于空字符)。这将根据从命令行调用程序的方式而改变,但您不能假设它在末尾有更多空间来连接更多字符。如果需要更多空间,则需要自己制作(使用 malloc 或变长数组等)。
  • 我明白,按照所有逻辑,这应该在每次运行时都会失败,但我不应该只是认为它继续工作是愚蠢的运气
【解决方案2】:
strcat(dest, d_basedir);

实际上等价于:

strcat(argv[2], d_basedir);

这是未定义的行为。它可能今天有效,明天失败。您有权写信至argv[2][0]argv[2][strlen(argv[2])],但超过该元素(您对strcat 调用所做的操作)是未定义的行为。

【讨论】:

  • @johnsoga strcat(argv[2], d_basedir) 写入argv[2][strlen(argv[2])]argv[2][strlen(argv[2]) + 1]argv[2][strlen(argv[2]) + 2] 等。写入argv[2][strlen(argv[2])] 是可以的(空终止符是原始字符串的一部分),但是写入到argv[2][strlen(argv[2]) + 1] 并且下一个元素是未定义的。
【解决方案3】:

它有效,因为你很幸运。就是这样;-)

通过附加到 dest,您将覆盖程序已分配的一些内存,但它不会将其用于任何重要的事情。所以这就是它“起作用”的原因。

您不能重新分配不是由 malloc 分配的内存。传递给 main() 的参数就是这些内存部分之一。

你想要的是为新路径分配足够大的新内存,然后将你需要的 strcpy 和 strcat 放入其中。

【讨论】:

    【解决方案4】:

    strcat 不关心dest。它只是一个指向 char 的指针,对于 strcat 来说已经足够了。

    由于argv[2] 来自环境,因此不允许添加到 dest (argv[2])。正确的做法是分配足够的内存,将argv[2]复制进去,然后在上面追加d_basedir

    char *dest = malloc(strlen(argv[2]) + strlen(d_basedir) + 1);
    strcpy(dest, argv[2]);
    strcat(dest, d_basedir);
    

    【讨论】:

      【解决方案5】:

      我个人不会对这类代码使用 realloc/malloc。

      您可以使用 PATH_MAX(或在某些情况下为 MAX_PATH)来确定您需要的最长路径。

       char dest[PATH_MAX]; 
      
       strcpy(dest, d_basedir);
       strcat(dest, argv[2]); 
      

      (这与你写的略有不同,它将 src-path 的 d_basedir 附加到 dest 的末尾,这对我来说似乎是错误的)

      【讨论】:

        猜你喜欢
        • 2021-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-17
        • 1970-01-01
        • 1970-01-01
        • 2020-10-18
        相关资源
        最近更新 更多