【问题标题】:strcpy behaving differently if destination string is uninitialized如果目标字符串未初始化,strcpy 的行为会有所不同
【发布时间】:2011-11-26 23:10:35
【问题描述】:

我正在使用 C 语言尝试创建一个霍夫曼解码器。这段代码只有在 codearray 未初始化时才有效,否则它会给我一个分段错误。但是,valgrind 抱怨如果我这样做,codearray 是未初始化的。我用 ddd 完成了它,一旦调用 strcpy 就会发生分段错误,我不知道为什么。

void printtree_inorder(node* n,char* code,char* letarray,char** codearray)
{
    if (n == NULL) {
        return;
    }
    static int counter=0;
    appenddigit(code,'0');
    printtree_inorder(n -> left,code,letarray,codearray);
    remdigit(code);
    if (n->let!='\0') {
       letarray[counter]=n->let;
       strcpy(codearray[counter],code);
       counter++;
    }
    appenddigit(code,'1');
    printtree_inorder(n -> right,code,letarray,codearray);
    remdigit(code);
}

这里是调用函​​数:

char code[100]={'\0'};
char** codearray=(char**)malloc(numchars*sizeof(char*));
for (i=0;i<numchars;i++) {
    codearray[i]=(char*)malloc(100*sizeof(char));
}


char* letarray=(char*)malloc((numchars+1)*sizeof(char));
letarray[0]='\0';

printtree_inorder(root,code,letarray,codearray);

【问题讨论】:

  • 你能展示执行分配和调用这个函数的代码吗
  • appenddigit 和 remdigit 是做什么的?
  • numchars 的值是多少?还有为什么你的计数器被声明为静态的?

标签: c string huffman-code


【解决方案1】:
for (i=0;i<numchars;i++) {
    codearray[i]=(char*)malloc(100*sizeof(char));
}

这就是你说的代码?它不是真正的初始化代码,它是为数据代码腾出空间。

char** codearray=(char**)malloc(numchars*sizeof(char*));

只是为您创建一个 char * 数组,但它们不指向任何有效内存。 因此,您的“初始化代码”只是确保您的内存是正确创建的。

真正让我害怕的另一件事是,您的计数器变量是静态的。 打电话

printtree_inorder(root,code,letarray,codearray);
printtree_inorder(root,code,letarray,codearray);

也会以分段错误结束,因为当您第二次(从外部)调用它时,计数器将是 > 然后是 numchars。 所以,让我们重写一下你的代码,让它更安全

char* code = (char *)malloc(numchars + 1);
memset(code, 0, numchars + 1);

char* letarray = (char *)malloc(numchars + 1);
memset(letarray, 0, numchars + 1);

char** codearray = (char **)malloc(numchars * sizeof(char *));
memset(codearray, 0, numchars * sizeof(char *));

printtree_inorder(root, code, letarray, codearray, 0);

free(code);
// do not forget the free the other allocations later as well as


void printtree_inorder(node* n,char* code,char* letarray,char** codearray, int counter)
{
    if (n == NULL) {
        return;
    }
    appenddigit(code,'0');
    printtree_inorder(n -> left,code,letarray,codearray, counter);
    remdigit(code);
    if (n->let!='\0') 
    {
       letarray[counter] = n->let;
       codearray[counter] = strdup(code);
       ++counter;
    }
    appenddigit(code,'1');
    printtree_inorder(n -> right,code,letarray,codearray, counter);
    remdigit(code);
}

【讨论】:

  • 这似乎可行,但后来当我调用 strcmp("string",codearray[i]) 时,它会因分段错误而崩溃
  • @Free_D,您确定 i 是
【解决方案2】:

可能在“初始化”调用中,数组根本没有真正正确初始化,因此函数崩溃。

当“未初始化”时,数组可能包含(偶然)不会导致分段错误的值,具体取决于程序之前对最终用于 codearray 的内存所做的操作。

该函数尝试将字符串复制到codearray[counter] 指向的任何位置:

strcpy(codearray[counter],code);

在函数调用中,您显示此 codearray[counter] 是一个随机值,因为只有数组被 malloc'ed,但元素未初始化为任何特定值。 strcpy() 然后尝试写入该随机内存地址。

您必须为字符串的副本分配内存,例如使用strdup() 而不是strcpy()

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-03
  • 1970-01-01
  • 2012-01-07
  • 2013-04-13
  • 2013-10-04
  • 2015-01-31
  • 1970-01-01
相关资源
最近更新 更多