【问题标题】:Can't copy characters from pointer to another pointer(both with memory allocated)无法将字符从指针复制到另一个指针(均已分配内存)
【发布时间】:2013-09-22 14:01:21
【问题描述】:

我有一个程序可以从命令行使用 argv 接受字符输入。我使用 strcpy 将输入 argv[1] 复制到已分配内存的名为 structptr 的指针(它从 struct 转到 structptr->words)。然后,我从指针 structptr 指向另一个指针的内存中逐个字符地复制该指针,该指针指向已分配的内存。在我复制了一个字符后,我打印该元素 [c] 以确保它已被正确复制(它具有)。然后我完成了所有字符的复制并将结果返回给一个字符指针,但由于某种原因它是空白/空。每次复制字符后,我都会检查前面的元素是否正确,但它们不再显示([c-2]、[c-1]、[c])。这是我的代码:

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

struct StructHolder {
char *words;
};
typedef struct StructHolder Holder;

char *GetCharacters(Holder *ptr){
int i=0;
char *words=malloc(sizeof(char));
for(i;i<strlen(ptr->words);i++){
 words[i]=ptr->words[i];
 words=realloc(words,sizeof(char)+i);
}
words[strlen(ptr->words)]='\0';
return words;
}

int main(int argc, char **argv){

Holder *structptr=malloc(sizeof(Holder));
structptr->words=malloc(strlen(argv[1]));
strcpy(structptr->words, argv[1]);
char *charptr;
charptr=(GetCharacters(structptr));
printf("%s\n", charptr);

return 0;

【问题讨论】:

  • 你需要使用调试器。
  • 我返回的结果指针似乎没有保存我从 ptr->words char by char 传输的内容。如果我在那一刻进行测试,它将显示 words[3] 打印 r 例如。如果我在那之前检查任何东西,什么都不会存在。当我返回指针并尝试在 main 中打印 charptr 时,我什么也没有得到或为 null。
  • 您应该按照其他人的建议进行操作,只需使用 1 个 malloc 和一个 strcpy。但是,出于学术目的,您的代码中的错误是 words=realloc(words,sizeof(char)*(i+2))
  • sizeof(char) 被定义为始终为1,因此在这种情况下无需使用它。如果您担心类型会在未来发生变化,您可以使用sizeof(*words)

标签: c


【解决方案1】:

仅供参考:您的描述涉及structptr,但您的代码使用struct StructHolderHolder

这段代码是一场灾难:

char *GetCharacters(Holder *ptr){
    int i=0;
    char *words=malloc(sizeof(char));
    for(i;i<strlen(ptr->words);i++){
        words[i]=ptr->words[i];
        words=realloc(words,sizeof(char)+i);
    }
    words[strlen(ptr->words)]='\0';
    return words;
}

应该是:

char *GetCharacters(const Holder *ptr)
{
    char *words = malloc(strlen(ptr->words) + 1);
    if (words != 0)
        strcpy(words, ptr->words);
    return words;
}

甚至:

char *GetCharacters(const Holder *ptr)
{
    return strdup(ptr->words);
}

所有这些都接受传递结构类型是有意义的;没有明显的理由为什么您不直接传递 const char *words

剖析“灾难”(并忽略参数类型):

char *GetCharacters(Holder *ptr){
    int i=0;

到目前为止还可以,尽管您不打算更改结构,因此它可以是 const Holder *ptr 参数。

    char *words=malloc(sizeof(char));

分配一个字节的成本很高——比调用strlen() 的成本更高。这不是一个好的开始,尽管它本身并没有错。但是,您不会检查内存分配是否成功。这是一个错误。

    for(i;i<strlen(ptr->words);i++){

i; 第一个词很奇怪。你可以写for (i = 0; ...(并且可能在i的定义中省略初始化器,或者你可以写for (int i = 0; ...

在这样的循环中反复使用strlen() 也是个坏消息。你应该使用:

    int len = strlen(ptr->words);
    for (i = 0; i < len; i++)

下一步:

        words[i]=ptr->words[i];

这个作业没有问题。

        words=realloc(words,sizeof(char)+i);

这个realloc() 分配有问题。如果你取回一个空指针,你就失去了对先前分配的内存的唯一引用。因此,您需要单独保存返回值,对其进行测试,并仅在成功时分配:

        void *space = realloc(words, i + 2);  // When i = 0, allocate 2 bytes.
        if (space == 0)
            break;
        words = space;

这样会更好/更安全。它不是完全干净的;最好将break; 替换为{ free(words); return 0; } 以提前退出。但是,一次分配一个字节的整个业务并不是正确的做法。你应该算出要分配多少空间,然后一次性分配。

    }
    words[strlen(ptr->words)]='\0';

您可以通过使用i 而不是strlen(ptr-&gt;words) 来避免重新计算长度。如果 if (space == 0) break; 被执行,这将具有正确的副作用。

    return words;
}

这个函数剩下的就OK了。

我没有花时间分析main();然而,它并非没有问题。

【讨论】:

    【解决方案2】:

    在这两行中,

    structptr->words=malloc(strlen(argv[1]));
    strcpy(structptr->words, argv[1]);
    

    需要将大小加一以容纳 nul 终止符。 strlen(argv[1]) 应该是 strlen(argv[1])+1

    我认为循环中也发生了同样的事情,它应该大 1。而 sizeof(char) 按照定义总是 1,所以:

     ...
     words=realloc(words,i+2);
    }
    words=realloc(words,i+2); // one more time to make room for the '\0'
    words[strlen(ptr->words)]='\0';
    

    【讨论】:

      【解决方案3】:

      一开始我以为是这个问题:

      char *words=malloc(sizeof(char)) 正在分配 1 个字节(大小为 1 个字符)。您的意思可能是 char *words = malloc(strlen(ptr-&gt;words)+1); - 您可能想对 ptr 进行空检查,并且它是成员,以确保安全。

      然后我看到了realloc。您的 realloc 始终短 1 个字符。当 i = 0 时,您分配 1 个字节然后进入循环,递增 i 并将一个 char 1 放在重新分配数组的末尾(在索引 1 处)

      您在 main 中的 strcpy 也没有在持有人中分配任何内存。

      【讨论】:

      • 对我来说是个坏例子。我实际上在我的示例中删除了 realloc 并在 malloc 中将大小设置为 100 ,但我仍然遇到同样的问题。至于 malloc 最初我希望有 1 个字节用于传输第一个字符,然后在 realloc +1 字节后用于每次额外传输
      • 我认为问题是你的 strcpy 在 main 正在写入未分配的内存。
      • 拍摄对不起,我不得不重新输入所有内容,并且在执行 strcpy 之前我从结构中做了 malloc 单词。将编辑该
      • 编辑您的问题以获得正确的代码。您使用的输入、预期输出和实际输出。
      • 我正确地将字符从 ptr->words 传递到 words 对吗? & 和 * 有时会让我感到困惑。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-27
      • 1970-01-01
      • 2021-02-07
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      相关资源
      最近更新 更多