【问题标题】:Seg fault on last line of code最后一行代码的段错误
【发布时间】:2012-01-01 20:03:14
【问题描述】:

我希望实现一个简单的分子动力学程序。我的第一步是将系统定义为一系列原子,每个原子都有一个类型、一个 ID 号、一个 3 维位置向量和一个 3D 速度向量。下面是我为此编写的程序:

FILE *init;

static int randomVelocity(void)  
{  
     return rand()/RAND_MAX - 0.5;  
}  


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

    int iType;  
    int iID;  
    int i;  
    double* pdPosition;  
    double* pdVelocity;  
    char* line;  
    Atom* poAtoms;  
    int count = 0;  

    init = fopen("newdat.txt", "r+");  
    srand((unsigned)time(NULL));  
    line = malloc(81*sizeof(char));  
    while (fgets(line, 80, init) != NULL)    
    {  
         char* tok1;  
         char* tok2;  
         char* tok3;  
         char* tok4;  
         tok1 = strtok(line, " \t");  
         if ((tok1 == NULL) || (tok1[0] == '*'))   
         {  
              break;  
         }  
         tok2 = strtok(NULL, " \t");  
         tok3 = strtok(NULL, " \t");  
         tok4 = strtok(NULL, " \t");  
         iType = atoi(tok1);  
         iID = count;  
         pdPosition = (double*)malloc(3*sizeof(double));  
         pdVelocity = (double*)malloc(3*sizeof(double));     
         pdPosition[0] = atof(tok2);  
         pdPosition[1] = atof(tok3);  
         pdPosition[2] = atof(tok4);  
         pdVelocity[0] = randomVelocity();  
         pdVelocity[1] = randomVelocity();    
         pdVelocity[2] = randomVelocity();  
         poAtoms[count] = Atom_new(iType, iID, pdPosition, pdVelocity);  
         count++;  
    }  

    for (i = 0; i < count; i++)  
    {  
         Atom_print(poAtoms[i]);  
         Atom_free(poAtoms[i]);  
    }   

    free(line);  
    return 0;  
}

这是头文件atom.h:

/**** atom.h ****/


typedef struct Atom_str *Atom;  

Atom Atom_new(int iType, int iID, double* adPosition, double* adVelocity);  

void Atom_free(Atom oAtom);  

void Atom_print(Atom oAtom);  

和测试输入文件:

1 5 7 9  
2 12 13 14  

程序可以编译,但是当我运行它时,我得到了预期的输出,然后是一个段错误。我正在使用 GDB 调试器,段错误似乎发生在代码的最后一行,在 return 语句之后!是内存管理问题吗?

【问题讨论】:

  • 这些类型的问题通常与内存损坏有关。您能否在 GDB 崩溃后键入“bt”并查看是否有堆栈跟踪,如果有则发布?或者使用 Valgrind。
  • 这是您指的堆栈跟踪吗? #0 0x0804b3fd 在?? () #1 0x00000001 在?? () #2 0xffffd8b4 在?? () #3 0xffffd8bc 在?? () #4 0x00722828 在?? () #5 0x00000000 在?? ()

标签: c segmentation-fault


【解决方案1】:

你从来没有malloced 内存为poAtoms。写入未初始化指针指向的任何位置很容易导致段错误。

在开始读取文件之前,应该分配一些空间,

unsigned expected_count = 2; // for the test input file, would be much larger in real runs
poAtoms = malloc(expected_count*sizeof(*poAtoms));

然后您必须在读取循环内部检查您没有写入超过分配的内存。之前

    poAtoms[count] = Atom_new(iType, iID, pdPosition, pdVelocity);

插入支票,

    if (expected_count <= count)
    {
        expected_count *= 2;   // double the space, could also be a smaller growth factor
        Atom *temp = realloc(poAtoms, expected_count*sizeof(*poAtoms));
        if (temp == NULL)
        {
            perror("Reallocation failed, exiting\n");
            exit(EXIT_FAILURE);
        }
        poAtoms = temp;
    }

如果为poAtoms 分配的空间已被使用,请尝试使用realloc 获取更多空间,如果失败,则中止,除非您知道如何修复它。如果重新分配成功,我们可以继续收集新的原子。

【讨论】:

  • 感谢您的回复,丹尼尔!我正在为 atom.c 文件提供代码:struct Atom_str { int iType;国际身份证;双* pdPosition;双* pdVelocity; }; Atom Atom_new(int iType, int iID, double* adPosition, double* adVelocity) { Atom oAtom; oAtom = (Atom)malloc(sizeof(struct Atom_str)); if (oAtom == NULL) 返回 NULL; oAtom->iType = iType; oAtom->iID = iID; oAtom->pdPosition = adPosition; oAtom->pdVelocity = adVelocity;返回 oAtom; }
  • 抱歉那里的格式很奇怪......但我的意思是我使用“oAtom = (Atom)malloc(sizeof(struct Atom_str)) 行为原子结构做了 malloc 空间;"也许我没有分配足够的内存?
  • 好吧,这无关紧要,因为在声明Atom* poAtoms; 和写poAtoms[count] = Atom_new(iType, iID, pdPosition, pdVelocity); 之间,根本没有提到poAtoms。所以poAtoms 指向意外占据其在堆栈上的位置所指示的任何位,这就是写入Atom_new 的返回值的位置。在您的情况下,这似乎覆盖了部分程序退出代码。
  • @user1125353 你是mallocing struct Atom_str,有效载荷,但不是Atom 指向有效载荷的指针。
  • 好吧,我想我明白了……你是说 poAtoms 实际上是一个指针数组吗?在这种情况下,我应该将其声明为“Atom** poAtoms;”吗?然后我应该包括像“poAtoms[count] = (Atom*)malloc(sizeof(int));”这样的行吗? (因为指针只是一个 int 地址,对吗?)
【解决方案2】:

tok1[0] 在 if 条件下做什么?当您尝试打印 tok1[[0] 时,您检查了 strtok 的小代码 sn-p 吗?

【讨论】:

    【解决方案3】:

    你能解释一下 1 5 7 9 在输入文件中代表什么吗?他们是类型 id 和 velocity 吗? 如果是这样,您可以通过连字符来操作和区分它们,并通过 strtok 将每个值提取为 NULL。还要检查 fgets 是否附加 NULL 或者可能是 *,因为您尝试检查 if 条件可能是 End of line 。我有一种直觉,它可能是你出错的地方,或者如果你能解释你的输入文件,那会很有帮助

    【讨论】:

    • 感谢您的回复! 1是原子类型; 5、7 和 9 应该分别是位置向量的 x、y 和 z 分量。 (速度向量的三个分量由随机数生成器提供。)我的代码的 if (tok1[0] == '') 部分应该让我的输入文件有 cmets,由 ''...但我可能需要多考虑一下! :)
    猜你喜欢
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多