【问题标题】:memcpy() not working as expected when copying pointers复制指针时 memcpy() 无法按预期工作
【发布时间】:2021-03-15 22:09:16
【问题描述】:

我想将char **pointer 的内容复制到另一个指针。我的尝试是:


void test(char **arr, int len) {
    printf("1: ");
    printArr(arr, len);
    char ***res = malloc(sizeof(char **));
    res[0] = malloc(sizeof(char *) * len);
    memcpy(&res[0], arr, len);
    printArr(res[0], len); 

这里我只想将包含多个字符串的arr 的内容复制到r[0],其中len 表示arr 中的元素数。但是,在检查res[0] 时,我意识到它只存储了两次 null。可以看出我是一个非常初学者,并且已经学习了几天 C,所以可能会出现一些简单的错误。

【问题讨论】:

  • 双指针已经很麻烦了。这里的三重指针(!!!)是什么?你只分配一个元素,你只使用一个元素。一个元素数组应该是一个变量。
  • 这段代码真的没有任何意义。我越看它,我就越想知道发生了什么。这是如何使用的?它有什么用途?
  • @tadman 三重指针应该指向不同的字符串数组。我创建了不同的字符串数组并想检查它们是否尚未创建,因此我将它们存储在 res 中以记住哪些字符串数组已创建。这似乎效率低下,但由于它是一个带有用户输入的动态应用程序,我还没有找到更简单的解决方案
  • 我意识到它只存储了两次 null。它应该存储什么?我们无法从这个不完整的代码 sn-p 中分辨出来。请以minimal verifiable example 的形式提供完整代码。还包括确切的预期结果与实际结果。
  • 长度为 1 的数组并不是真正的数组

标签: c pointers memcpy


【解决方案1】:
char ***res = malloc(sizeof(char **));
res[0] = malloc(sizeof(char *) * len);
memcpy(&res[0], arr, len);

第一行为单个char ** 分配空间并让res 指向它

第二行为len 指向char 的指针数组分配空间,并使res[0] 指向它。

第三行将来自 arr 的 len byes 复制到 res 指向的内存顶部,覆盖第二次 malloc 调用的结果,然后在第一次 malloc 调用分配的块之后在内存上乱写。

你可能真的想要类似的东西

mempy(res[0], arr, len * sizeof(char*));

这会将 len 指针数组(由 arr 指向)复制到第二个 malloc 调用分配的内存中。

【讨论】:

  • 不幸的是,当您尝试使用printf("%s", res[0][0]); 打印复制数组的第一个字符串时,您的解决方案给了我一个 SEG FAULT。 arr 的形式为 {"ab", "bc", "cd"}
  • 这可能意味着arr 不正确(或len 错误),或者您将其错误地传递给您的函数。
【解决方案2】:

如果这是一个你需要深拷贝的C字符串数组:

char** array_deep_copy(char **arr, int len) {
    // calloc() makes "allocation of N" calculations more clear
    // that this is N allocations of char* becoming char**
    char **res = calloc(len, sizeof(char*));

    for (int i = 0; i < len; ++i) {
      // Use strdup() if available
      res[i] = strdup(arr[i]);
    }

    return res;
}

请注意,这需要一个适当的释放函数,该函数将遍历并递归free() 那些克隆的字符串,否则内存泄漏

如果只需要浅拷贝:

char** array_shallow_copy(char **arr, int len) {
    char **res = calloc(len, sizeof(char*));

    // memcpy(dest, src, size) is usually more efficient than a loop
    memcpy(res, arr, sizeof(char*) * len);

    return res;
}

这个不需要递归的free(),你只需free()顶级指针就可以了。这与原始数据共享数据,因此如果在此结构之前释放这些指针中的任何,那么您将在其中包含无效的指针。小心!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多