H asked in 電腦與網際網路程式設計 · 1 decade ago

在Linux上面執行程式Segmentation fault

在Linux上面執行程式出現Segmentation fault

我是再執行一個副程式的時候,在還沒有進入這個副程式前都OK,我有故意在CALL副程式前就先printf("OK\\n");的字樣,有成功印出來,然而在進入副程式後,一進去啥事情都不做,先來個printf,就不能印出來了!!

請問這樣該如何DEBUG呢??

有人說我這個程式可能是用到一些LINUX不支援的函式還是怎樣,堆疊錯誤阿等等ㄉ才會出現這種訊息!

我#include了這些表頭

math.h

stdlib.h

stdio.h

string.h

用到比較奇怪的參數就是argv[],不過這種傳法在其他副程式就可以正常執行哩?!

還有使用到一個sprintf這是我最近透過發問才學到的

會不會是這些原因呢??

請高手幫忙吧!!THX~~

Linux上面的gdb要如何使用呢??會得話可以教一下ㄇ~~感恩

Update:

void Modify_value_symbol(int del_module_def_or_extract_only_module_def,Net_Symbol_ListNode *Net_Symbol_vcd_head,Value_Symbol_ListNode *Value_Symbol_vcd_head,char *argv[])

{

Update 2:

Value_Symbol_ListNode *p,*pre_p,*q,*pre_q;

int the_same_delay_time_mark=0;

long base_delay_time,delay_time;

char simulation_time_temp[15];

String str_temp;

Update 3:

String str_temp; ==========這個不是,這行貼錯了

Update 4:

//del_module_def_or_extract_only_module_def=1 = extract module definition form the module_definition_link_list in value_symbol_link_list, and other not in module_definition_link_list

if(del_module_def_or_extract_only_module_def)

{

Update 5:

strcpy(simulation_time_temp,Value_Symbol_vcd_head- next- symbol);

simulation_time_temp[0]='0';

for(int index=1;index next;p!=NULL;p=p- next)

for(Value_Symbol_ListNode *q=Value_Symbol_vcd_head- next;q!=NULL;q=q- next)

Update 6:

{

strcpy(temp1,p- symbol);

strcat(temp1,"\n\0");

strcpy(temp2,q- symbol);

if(temp2[0]=='#' && q- value[0]=='\0')

{

q- flag=1; //Preserve the delay information

}

Update 7:

else if(!(strcmp(temp1,temp2)))

{

q- flag=1; //Preserve the q node

}

else

{

if(q- flag!=1)

q- flag=0; //Useless the q node

}

}

Update 8:

for(Value_Symbol_ListNode *pre_q=Value_Symbol_vcd_head,*q=Value_Symbol_vcd_head- next;q!=NULL;q=q- next)

{

if(q- flag==0)

{

pre_q- next=q- next;

free(q);

//pre_q in the next turn doesn't move

q=pre_q;

}

Update 9:

else

{

if(q- symbol[0]=='#' && q- value[0]=='\0')

{

Update 10:

strcpy(simulation_time_temp,q- symbol);

simulation_time_temp[0]='0';

for(int index=1;index

Update 11:

{

if(simulation_time_temp[index]=='\n')

{

simulation_time_temp[index]='\0';

break;

}

}

simulation_time=atol(simulation_time_temp);

Update 12:

simulation_time-=simulation_base_time;

sprintf(simulation_time_temp,"#%ld\n\0",simulation_time);

strcpy(q- symbol,simulation_time_temp);

}

pre_q=pre_q- next;

}

}

}

Update 13:

else

{

for(Net_Symbol_ListNode *p=Net_Symbol_vcd_head- next;p!=NULL;p=p- next)

Update 14:

for(Value_Symbol_ListNode *pre_q=Value_Symbol_vcd_head,*q=Value_Symbol_vcd_head- next;q!=NULL;q=q- next)

{

strcpy(temp1,p- symbol);

Update 15:

strcat(temp1,"\n\0");

strcpy(temp2,q- symbol);

if(!(strcmp(temp1,temp2))) //Delete q node

{

pre_q- next=q- next;

free(q);

//pre_q in the next turn doesn't move

q=pre_q;

}

Update 16:

else

{

pre_q=pre_q- next;

}

}

}

}

Update 17:

呼~~貼完那段副程式了,除了上面定一的一行貼錯外,那行不要,其他應該都沒貼錯,不過有些符號無法顯示,大概幫我看看我是不是用了啥不該用ㄉ東西THX~~

Update 18:

在gdb下出現這個訊息,然後要怎麼找bug呢?

Program received signal SIGSEGV, Segmentation fault.

0x420807b0 in strcpy () from /lib/i686/libc.so.6

Update 19:

已經下班了,不過剛剛看到你說我strcpy()可能是拷貝過去,目的地沒有足夠的空間,才會錯,我剛剛查了一下,發現

strcpy(temp1,p- symbol);

strcat(temp1,"\n\0");

1 Answer

Rating
  • Rody
    Lv 5
    1 decade ago
    Favorite Answer

    你這錯誤訊息說明了你存取了不正確的記憶體位址, 根據你提供的程式碼, 程式當中大量使用字串複製和字串連接的動作, 而且根據你的錯誤訊息, 問題是出在 strcpy 函式, 因此可以知道你的程式錯在某行 strcpy你的程式碼只有提供副函式, 沒有辦法整個編譯, 因此我沒辦法告訴你正確出錯的位置, 要找到正確出錯的位置很簡單, 如果你用 gdb 來偵錯, 你只要一行一行來執行, 你就可以知道出錯的是哪行就算不用 gdb 來偵錯, 你還是可以很輕易地利用類似 puts, printf, cout 之類的東西來偵錯, 做法就是你在每行程式碼後面都加一行類似 puts("step 1");puts("step 2");... 如此一來, 你就可以知道當發生錯誤時, 程式已經執行到哪行; 當然, gdb 是個很強大很好用的除錯工具, 花點時間學習他是一定值得的, 學習可以看線上手冊, 找網路資訊, 看書, 方法隨你選在這個例子當中, 除錯是相對容易的事情, 但我必須說, 你程式這樣的架構並不是很好, 你的程式碼使用的這些字串相關函式, 都必須在你的字串緩衝區提供足夠大小的空間給他們使用, 才會正常運作, 而以你的程式動作而言, 程式碼的複雜程度讓人無法立刻知道到底實際需要多少的空間來進行這些字串操作, 所以我相信你程式的問題也是因此發生, 而且即使你這次利用除錯, 發現你到底少給了哪些字串多少空間, 依然無法確保下次同樣的函式呼叫不會出問題, 所以你的問題是在於一開始就使用了不安全的程式碼關於這個問題的根本解決之道, 不僅僅是把眼前的問題解決, 而是也許你應該採用別的元件, 別的演算法, 例如使用 string 來取代 char *, 利用 string 本身就提供的 operator+() 和 operator=() 來取代 strcat 和 strcpy, 讓 string 本身來處理記憶體配置的問題, 你才不會為了這種記憶體配置不良的問題來頭痛

    2006-09-15 12:33:31 補充:

    我說的是 string 而不是 String,string 是 STL ﹙標準模板函式庫﹚的容器,大部分的 C++ 編輯器都有支援,你說的 String 是 C++ Builder 自己的函式庫的東西,不一樣,那東西只能適用於 C++ Builder。

    2006-09-15 12:37:35 補充:

    另外,我想不是 Linux 機車跟你過不去,應該是你實際使用到的位址確實超出你宣告的範圍才會出錯,編譯器編譯成功可以執行,代表編譯器的工作已經結束,你會出現記憶體的錯誤只是告訴你,你真的存取到不屬於你的記憶體,他出錯是系統的自我保護機制,你應該感謝他只是出錯,Windows 不出錯的結果,哪天當掉都不知道是哪邊的問題

    2006-09-15 12:41:24 補充:

    執行 printf("%s\n",Value_Symbol_vcd_head- next- symbol); 會掛掉,代表 symbol 可能在他的字串範圍內,已經找不到 NULL 這個字串結束字元,如此一來,printf 就有可能存取到不屬於你的記憶體,當然會出錯了。

    2006-09-15 12:45:57 補充:

    在 gdb 下面下 print "%s",Value_Symbol_vcd_head- next- symbol 這個指令,也會遇到和上面相同的問題,總而言之,在你程式即將出錯的這個時候,你的 symbol 已經有問題了,問題不是在這邊,而是在更前面的一個字串銜接指令,你在這個出問題的地方利用 strlen 查詢要銜接的兩個字串長度是否有超過你的允許字串長度,我想你就會發現問題

    2006-09-15 12:54:14 補充:

    我還是強調,找到你這次的問題不難,但如果你保持這樣的程式架構,我只能說你是埋了個不定時炸彈給自己比較恰當的方式有兩種,一種是改用 string 來取代 char *,你只要稍微花點時間看看 string 怎麼使用就可以﹙新一點的 C++ 的基礎書上都會提到﹚,但缺點是你得改變原來的架構,變更會比較多;第二種方法是你在傳入 char * 的時候,順便傳入允許的最大緩衝區尺寸,如此一來在你要進行 strcat 之前,只要先檢查兩個字串長度加起來是否還在範圍內,在才使用 strcat,不在就出現錯誤訊息返回,這樣才能確保你的程式不會有問題

Still have questions? Get your answers by asking now.