memset()没有在c中设置内存

Posted

技术标签:

【中文标题】memset()没有在c中设置内存【英文标题】:memset() not setting memory in c 【发布时间】:2013-11-25 20:52:37 【问题描述】:

如果我的格式不正确,我深表歉意,因为这是我的第一篇文章,我在网站上找不到处理我遇到的相同问题的帖子。我在 ubuntu 12.04 服务器上使用纯 C。我试图将几个字符串连接成一个字符串,由 Ns 分隔。但是,字符串大小和字符串之间的间距可能会有所不同。制作了一个结构来将位置数据存储为可以传递给多个函数的几个整数:

typedef struct pseuInts   
    int pseuStartPos;  
    int pseuPos;  
    int posDiff;  
    int scafStartPos;  
 pseuInts;  

还有一个字符串结构:

typedef struct string   
    char *str;  
    int len;  
 myString;

由于连接字符串存在中断条件,因此将动态链接列表的多个节点组装在一起,其中包含标识符和连接字符串:

typedef struct entry   
    myString title;  
    myString seq;  
    struct entry *next;  
 entry;  

memset调用如下:

 else if ((*pseuInts)->pseuPos != (*pseuInts)->scafStartPos)   
    (*pseuEntry)->seq.str = realloc ((*pseuEntry)->seq.str, (((*pseuEntry)->seq.len) + (((*pseuInts)->scafStartPos) - ((*pseuInts)->pseuPos)))); //realloc the string being extended to account for the Ns  
    memset (((*pseuEntry)->seq.str + ((*pseuEntry)->seq.len)), 'N', (((*pseuInts)->scafStartPos) - ((*pseuInts)->pseuPos))); //insert the correct number of Ns
    (*pseuEntry)->seq.len += (((*pseuInts)->scafStartPos) - ((*pseuInts)->pseuPos)); //Update the length of the now extended string  
    (*pseuInts)->pseuPos += (((*pseuInts)->scafStartPos) - ((*pseuInts)->pseuPos)); //update the position values  
  

如果决策是在由 main 调用的函数调用的函数中,则这些都被取消引用,但是对 pseuEntry 结构的更改需要在 main 中更新,以便传递给另一个函数以进行进一步处理. 我通过插入一些 printf 命令仔细检查了 pseuInts 中使用的数字,它们在需要添加多少 N 的位置上是正确的,即使它们在不同的短字符串之间发生变化。但是,当程序运行时,memset 仅在第一次调用时插入 Ns。即:

GATTGT 和 TAATTTGACT 用 4 个空格隔开,它们变成: GATTGTNNNNTAATTTGACT

第二次在相同的连接字符串上调用它却不起作用。即: TAATTTGACT 和 TCTCC 用 6 个空格隔开,所以长字符串应该变成:

GATTGTNNNNTAATTTGACTNNNNNNTCTCC 但它只显示: GATTGTNNNNTAATTTGACTTCTCC

我添加了 printfs 以在 memset 之前和之后显示连接的字符串,并且它们在输出中是相同的。 有时插入会添加额外的字符空间,但不会初始化它们,因此它们会打印出废话(正如预期的那样)。即:

GAATAAANNNNNNNNNNNNNNNN-GCTAATG 应该是 GAATAAANNNNNNNNNNNNNNNNNGCTAATG

我已经用 for 或 while 循环切换了 memset,我得到了相同的结果。我使用了一个中间 char * 来重新分配,仍然得到相同的结果。我正在寻找有关我应该在哪里尝试检测错误的建议。

【问题讨论】:

很好地描述了问题,只是很难看出所有取消引用的问题。如果您可以提供足够少的代码以便有人可以编译、构建、运行它,那么可能更容易排除故障?更容易看到发生了什么。 sscce 这不可能编译。 pseuInts 是第一个代码块中的类型,最后一个代码块中的变量 很好奇 - 使用 pseuInts.pseuPos 而不是 (*pseuInts)->pseuPos 会有什么问题? (等人) 由于我只使用一组通过执行不断更新的 pseuInts,我将其标记为:pseuInts *curPseuInts = malloc (sizeof (*curPseuInts));当它第一次出现时,然后将其传递给这些函数: void updatePseuEntryPosition (entry **pseuEntry, blastnEntry *blastnEntry, string *curChr, pseuInts **pseuInts); void endPseuEntry (entry **entry, string *chr, pseuInts *pseuInts);所以它既是类型又是变量。 (抱歉,我无法让格式适用于评论) memset被调用时,scafStartPos and pseuPos的值是多少? 【参考方案1】:

如果您可以考虑完全不同的方法,我想提供这个:

我理解您的意图:用相同数量的“N”替换两个字符串之间的现有空格。memset()(以及相关的内存分配)是执行连接的主要方法.

您描述的当前连接尝试的问题是:1) 垃圾嵌入结果字符串中。2 ) 在某些非预期内存位置写入“N”。3) “N”未写入其他预期内存位置。

不同的方法

第一:验证分配给正在修改的字符串的内存是否足以包含结果第二: 验证要连接的所有字符串在尝试连接之前都已终止 \0第三个​​: 使用 strcat() 和一个 for(;;) 循环来追加所有“N”,以及最终的后续字符串。

例如。

for(i=0;i<numNs;i++)//compute numNs with your existing variables 

    strcat(firstStr, "N");//Note: "N" is already NULL term. , and strcat() also ensures null term.

strcat(firstStr, lastStr); //a null terminated concatenation

我知道这种方法与您所做的有很大不同,但它至少可以解决您的问题陈述中确定的问题。如果这没有意义,请告诉我,我会尽可能解决问题。 (目前有其他项目正在进行中)

【讨论】:

抱歉回复晚了。我正在仔细检查我的方法是否已经按照您的建议进行,并且我缺少空终止符。我已经编辑了我的代码,以确保在每个被编辑的字符串之后都有一个 '\0' 并且它工作得很好。感谢您的帮助!【参考方案2】:

查看你的 memset:

memset (((*pseuEntry)->seq.str + ((*pseuEntry)->seq.len))), ...

这就是目的地。不应该是:

(memset (((*pseuEntry)->seq.str + ((*pseuEntry)->seq.len) + ((*pseuEntry)->seq.pseuStartPos))

否则我会错过pseuInts 的含义。

【讨论】:

你可能正在做一些事情,虽然我相信 OP 的声明意图是开始在 seq.str + seq.len 的末尾插入“N”,以计算 scafStartOis-pseuPos (缩写) .我在一个非常大的屏幕上看着它,一切都布置好了,但仍然很难看懂。一些可编译的代码会有所帮助。 抱歉回复延迟。 ryyker 的解释是准确的。我需要添加足够的 N 来填充从添加的最后一个字符串(由 pseuPos 保存)到下一个短字符串的开头(由 scafStartPos 保存)的空间。当它们位置重叠时使用 PseuStartPos,即如果字符串 X 在位置 5 结束并且字符串 Y 从位置 4 开始,那么我需要创建一个新的长字符串并将 pseuStartPos 更新为 4 而不是 1,以便将所有相对位置调整为那个新的开始位置。

以上是关于memset()没有在c中设置内存的主要内容,如果未能解决你的问题,请参考以下文章

零基础学C语言内存知识总结:memset函数和calloc函数

C结构体成员初始化memset

c语言里有memset()怎么用?需要啥头文件?

memset 与 memcpy

使用 memset 设置数组

我需要在 Swift 中 memset 一个 C 结构吗?