2012-01-01 80 views
3

我希望實現一個簡單的分子動力學程序。我的第一步是將系統定義爲一系列原子,每個原子都有一個類型,一個id號,一個​​3維位置矢量和一個3D速度矢量。下面是我寫這樣做的程序:代碼最後一行的Seg錯誤

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 

程序編譯,但是當我運行它時,我會得到期望的輸出,然後是seg故障。我正在使用GDB調試器,在return語句之後,seg錯誤似乎發生在最後一行代碼中!這是內存管理問題嗎?

+0

這些類型的問題通常與內存損壞有關。你可以在GDB崩潰後輸入「bt」,看看是否有堆棧跟蹤,如果是這樣的話就發佈它?或者使用Valgrind。 – 2012-01-01 20:07:04

+0

這是您所指的堆棧跟蹤? #0 0x0804b3fd在?? () #1 0x00000001在? () #2 0xffffd8b4在? () #3 0xffffd8bc在? () #4 0x00722828在? () #5 0x00000000在? () – user1125353 2012-01-01 21:06:36

回答

6

你從來沒有malloc ed內存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得到更多,如果失敗,中止,除非你知道如何解決它。如果重新分配成功,我們可以繼續收集新的原子。

+0

謝謝你的回覆,丹尼爾!我正在爲我的原子提供代碼。c文件:struct Atom_str { int iType; int iID; double * pdPosition; double * pdVelocity; }; Atom Atom_new(int iType,int iID,double * adPosition,double * adVelocity) {Atom oAtom; oAtom =(Atom)malloc(sizeof(struct Atom_str)); if(oAtom == NULL) return NULL; oAtom-> iType = iType; oAtom-> iID = iID; oAtom-> pdPosition = adPosition; oAtom-> pdVelocity = adVelocity; return oAtom; } – user1125353 2012-01-01 20:51:35

+0

對不起,這裏有奇怪的格式...但我的意思是說我使用行「oAtom =(Atom)malloc(sizeof(struct Atom_str))」爲原子結構做了malloc空間;我可能沒有足夠的記憶嗎? – user1125353 2012-01-01 20:54:51

+0

呃,這裏沒什麼關係,因爲在聲明'Atom * po'和'poAtoms [count] = Atom_new(iType,iID,pdPosition,pdVelocity)'之間,'沒有提到'poAtoms'。所以'poAtoms'指向意外佔據堆棧位置的位,並且這就是'Atom_new'的返回值被寫入的位置。在你的情況下,這似乎已經覆蓋了程序退出代碼的一部分。 – 2012-01-01 21:03:11

0

tok1 [0]在if條件下做什麼?你是否檢查了strtok的一個小代碼片段,當你嘗試打印tok1 [[0]時返回或檢查了什麼?

0

你能解釋1 5 7 9在輸入文件中代表什麼嗎?是我的類型id和速度。 如果是這樣,你可以通過連字符來操作和區分它們,並通過strtok將每個值提取爲NULL。還要檢查fgets是否追加了NULL,或者可能是*,因爲您試圖檢查條件是否可能爲行尾。我有一個感覺,它可能是你錯誤的地方,或者如果你可以請求解釋你的輸入文件,這將是有幫助的

+0

感謝您的回覆! 1是原子類型; 5,7和9應分別是位置矢量的x,y和z分量。 (速度矢量的三個分量由隨機數發生器提供。)我的代碼的if(tok1 [0] =='''')部分應該讓我的輸入文件有註釋,由'*'分隔。 ..但我可能需要通過更多的想法! :) – user1125353 2012-01-01 20:49:38