首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >条件跳转或移动取决于在for循环中使用strcat的未初始化值。

条件跳转或移动取决于在for循环中使用strcat的未初始化值。
EN

Stack Overflow用户
提问于 2021-10-01 06:56:16
回答 1查看 2.6K关注 0票数 0

我有一个包含3个染色体字符串的文件,我想把它连接到一个基因组中。然后,我必须跨多个线程访问这个连接字符串(我使用pthread_t)。为此,我必须在提取数据时使用pthread_mutex_lock,然后使用strcat连接使用const *函数fai_fetch提取的数据,然后将数据保存为char* (参见下文)。

代码语言:javascript
复制
// genome_size the size of all the chromosomes together
// chr_total the number of chromosomes I wish to concatenate
char* genome = (char*) malloc(sizeof(char) * (genome_size+chr_total));

for (int i = 0; i < chr_total; i++){
    pthread_mutex_lock(&data_mutex);
    const char *data = fai_fetch(seq_ref,chr_names[i],&chr_sizes[i]);
    pthread_mutex_unlock(&data_mutex);
    //sprintf(&genome[strlen(genome)],data);
    strcat(genome,data);  
    //sprintf(genome+strlen(genome),data); //All three gives conditional jump or move error

    //sprintf(genome,data); // THIS SOLVES VALGRIND ISSUE ONE BUT DOES NOT GIVE A CONCATENATED CHAR*
}

所有这些都很有效,但是我得到了

条件跳转或移动取决于引用“strcat(基因组,数据)”的未初始化值;

未初始化的值是通过引用"char*基因组= (char*) malloc(sizeof(char) *(genome_size+chr_total))“的堆分配来创建的;

在其他StackOverflow答案的基础上,我尝试了sprintf(&genomestrlen(基因组),data)和sprintf(genome+strlen,data);而不是strcat。然而,他们也给出了同样的英勇的信息。

唯一能缓解这一错误的方法是使用sprintf(基因组,数据);然而,我不会得到完整的基因组,而只是一个染色体。

尝试基因组+= sprintf(基因组,数据);给我./a.out':munmap_chunk():无效指针和./a.out':free()

关于“未经初始化的值是由堆分配创建的”错误->,那么我的问题是,只有在所有线程运行完之后,我才能释放该内存。因此,当我使用malloc时,我不知道如何初始化堆分配中的值。

有可能解决这些具体的价值错误吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-01 10:20:50

使用Val差伦来定位问题代码

“条件跳转或移动取决于未初始化的值”消息意味着Val差尔已经确定程序的某些结果依赖于未初始化的内存。使用--track-origins=yes标志跟踪未初始化值的来源。也许能帮你找到那个价值。来自man 1 valgrind

设置为yes时,Memcheck会跟踪所有未初始化值的起源。然后,当报告未初始化的值错误时,Memcheck将尝试显示值的来源。源可以是以下四个位置之一:堆块、堆栈分配、客户端请求或其他杂项源(例如,对brk的调用)。

更具体地说,在您的程序中:

问题1:使用未初始化的genome

线

代码语言:javascript
复制
char* genome = (char*) malloc(sizeof(char) * (genome_size+chr_total));

使用genome分配malloc(2)缓冲区,然后在以下文件中使用该缓冲区:

代码语言:javascript
复制
strcat(genome,data);

请注意,像strlen(3)strcat(3)这样的函数在C-字符串上工作,它们是以空字符('\0')终止的缓冲区。

malloc(2)只是分配内存,而不对其进行初始化,因此您分配的缓冲区可能包含任何值(并被认为是未初始化的)。您应该避免将字符串相关函数与未初始化的缓冲区一起使用,因为它会导致未定义的行为。

幸运的是,calloc(2)这样做了--它分配缓冲区并将其所有位初始化为零,从而得到一个有效的0长度C-字符串,您可以对其进行操作。我建议使用以下修复方法来确保初始化genome

代码语言:javascript
复制
char* genome = calloc(genome_size+chr_total+1, sizeof(char));

还请注意,我已经将+1添加到分配缓冲区的长度中。这样做是为了确保结果的genome将以空终止符结尾(假设genome_size+chr_total是从fai_fetch返回的所有缓冲区的总大小)。

还请注意,就性能而言,callocmalloc慢一点(因为它初始化了数据),但在我看来,它初始化整个缓冲区更安全。就特定程序而言,可以通过使用malloc并仅初始化第一个字节来节省性能负担:

代码语言:javascript
复制
char* genome = malloc(sizeof(char) * (genome_size + chr_total + 1));
if (NULL == genome) {
    perror("malloc of genome failed");
    exit(1);
}
// So it will be a valid 0 length c-string
genome[0] = 0;

我们不必将最后一个字节初始化为0,因为strcat为我们编写了终止空字符。

(潜在)问题2:在strcat中使用潜在的非空终止strcat

正如您在问题中所描述的,fai_fetch提取了一些数据:

代码语言:javascript
复制
const char *data = fai_fetch(seq_ref,chr_names[i],&chr_sizes[i]);

然后在strcat行中使用它:

代码语言:javascript
复制
strcat(genome,data);

正如我前面所写的,由于您使用的是strcat,所以data也应该以空结尾。

我不知道fai_fetch是如何实现的,但是如果它返回一个有效的C-字符串,那么您就可以了。

如果没有,那么您应该使用strncat,它可以工作在非空终止的缓冲区上。

来自man 3 strcat

strncat()函数类似,只是

  • 它将最多使用src中的n个字节;如果
  • src包含n个或多个字节,则不需要以空结尾。

我建议采取以下办法:

代码语言:javascript
复制
// I'm not sure what type `&chr_sizes[i]` is, assuming it's `size_t`
size_t length = &chr_sizes[i];
const char *data = fai_fetch(seq_ref,chr_names[i], length);
// Use strcat
strncat(genome, used_data, length); 
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69401709

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档