0

在下面的函数中,我从链表中解析字符串并为结构数组赋值。有什么方法可以让我不在 while 循环中使用 malloc。我无法处理 glibc 错误,所以寻找其他方法。我尝试使用 char 数组而不是 char* 作为结构字段。但我收到段错误。实际上该函数正在工作,但我必须在调用该函数 15000 次之后,所以我想确保它不会造成任何内存问题。

struct CoordNode
{
int resNum;
double coordX;
double coordY;
double coordZ;
char atomName[4];     
};
void parseCrdList()
{
int resNum=1;
int tAtomNum,i;
char *tcoordX, *tcoordY, *tcoordZ, *tatomName, tresNum[5]; 
ccur_node=headCoord_node->next;  
struct CoordNode *t;
t=malloc(numofRes*sizeof(struct CoordNode));
i=0;
while (ccur_node!=NULL)
{     
      tresNum=malloc(5*sizeof(char));
      memcpy(tresNum,ccur_node->crdRow+26,4);
      resNum=atoi(tresNum);                  
      t[i].resNum=resNum;
      tcoordX=malloc(8*sizeof(char));
      memcpy(tcoordX,ccur_node->crdRow+35,7);         
      tcoordY=malloc(8*sizeof(char));
      memcpy(tcoordY,ccur_node->crdRow+43,7);       
      tcoordZ=malloc(8*sizeof(char));
      memcpy(tcoordZ,ccur_node->crdRow+51,7);                        
      t[i].coordX=strtod(tcoordX,NULL);
      t[i].coordY=strtod(tcoordY,NULL);
      t[i].coordZ=strtod(tcoordZ,NULL);         
      tatomName=malloc(4*sizeof(char));         
      memcpy(tatomName,ccur_node->crdRow+17,3);        
      strcpy(t[i].atomName,tatomName);        
      old_ccur_node=ccur_node;
      ccur_node=ccur_node->next;
      //free(old_ccur_node);          
      i++;  
}
      numofRes=i;
      addCoordData(t);
      //free(t);
      t=NULL;
}
4

2 回答 2

0

一些想法和猜测。
首先,正如我之前提到的,sizeof(char)总是1 byte在 C 中,它实际上是 C 中的标准字节定义。所以删除那些完全不必要且难以阅读的内容。

回到主要问题。
您永远不会使用大于 8 的字符数组,因此只需使其静态长度为 8 个字节。如果您必须调用函数 15k 次,那将为您节省大量时间(malloc 需要时间为您分配内存)。

鉴于问题中的信息,我猜您的段错误是未初始化您使用 malloc 分配的内存或char [8]为其声明
1为 auto 保留的内存的原因。您分配(或第二版 - 声明 8 字节数组)8 字节。它工作正常。但是你在这里得到了 8 个字节的垃圾。

2.从列表中复制 7 个字节。这也很好。但是您忘记了 NULL 终止,因此如果您尝试将其打印回来,则会出现段错误。编辑如果它有效,那么您可能很幸运,因为它不应该。

解决方案
替换char *witch char [8],删除所有mallocs 和frees 对应于那些 char *、null terminate所有char[8]after strcpystrncpymemcpy(无论您的选择是什么,取决于您对列表中的数据正确的信心)数据给他们。

valgrind在进一步使用之前检查您的代码。

于 2013-11-14T00:28:13.873 回答
0

令人惊讶的是,您说此功能对您有用。从我从您的代码中看到的情况来看,我一开始就有很多内存泄漏,因为这些 8 字节的 malloc 都没有被炸过。

第二件事是,看起来您CoordNode在知道要解析的实际数据记录数之前分配数组。我在分配前添加了适当的numofRes计算。

由于您不修改输入数据,因此您实际上并不需要所有这些 malloc 和 memcpy ,因此假设它具有类型,您可以立即使用crdRowstrtod()char *

最后一件事:在一个地方进行分配并在另一个地方释放数据通常是一种不好的做法。因此,最好headCoord_node在解析后将结构释放到分配的位置。释放的决定t取决于如何addCoordData(t)处理它的参数。

void parseCrdList()
{
    struct CoordNode *t;
    int i;

    // count number of records to parse
    numofRes = 0;
    ccur_node = headCoord_node->next;
    while (ccur_node != NULL)
    {
        numofRes++;
        ccur_node=ccur_node->next;
    }
    t=malloc(numofRes*sizeof(struct CoordNode));

    i=0;
    ccur_node = headCoord_node->next;
    while (ccur_node!=NULL)
    {     
        t[i].resNum=atoi(ccur_node->crdRow+26);
        t[i].coordX=strtod(ccur_node->crdRow+35,NULL);
        t[i].coordY=strtod(ccur_node->crdRow+43,NULL);
        t[i].coordZ=strtod(ccur_node->crdRow+51,NULL);
        strncpy(t[i].atomName,ccur_node->crdRow+17,4);
        ccur_node=ccur_node->next;
        i++;  
    }
    numofRes=i;
    addCoordData(t);
    //free(t); // <<< it depends on how addCoordData treats t
}
于 2013-11-14T00:43:18.500 回答