2013-01-23 55 views
1

可能只是C新手的另一個愚蠢的指針問題。無法弄清楚這一點。似乎我的堆棧框架已損壞。這個任務似乎大多不相關,但這是一個相當基本的I/O練習。嘗試讀取一次讀取的結構數組(不能使用高級I/O函數,如fread())。錯誤讀取變量,無法訪問內存地址X

#include "A2_Phase2.h" 

void read_directory(Cdir directory[], int cnt) 
{ 
    int fd; 
    char filename[] = "RandomStructDir.bin"; 

    fd = open(filename, O_RDONLY, S_IRWXU); 
    if (fd < 0) 
     perror(strcat(filename, " failed to open.")); 

    if (read(fd, &(directory[0].code[0]), sizeof(Cdir) * cnt) < 0) { 
     perror(strcat(filename, " could not be accessed.")); 
    } 

    close(fd); 
} 

int binary_search(Cdir directory[], char *key, int l, int r) { 

    int mid = (int) r/2; 

    if (strncmp(key, directory[mid].code, 3) < 0) 
     return binary_search(directory, key, l, mid - 1); 
    else if (strncmp(key, directory[mid].code, 3) > 0) 
     return binary_search(directory, key, mid + 1, r); 
    else 
     return mid; 
} 

int main(int argc, char *argv[]) 
{ 
    int COUNTRY_COUNT = atoi(argv[1]); 
    printf("%d", COUNTRY_COUNT); 

    Cdir *directory = (Cdir *) malloc(sizeof(Cdir) * COUNTRY_COUNT); 
    read_directory(directory, COUNTRY_COUNT); 
    binary_search(directory, "ZWE", 0, 238); 
    free(directory); 
} 

我通過GDB收到此錯誤:

Program received signal SIGSEGV, Segmentation fault. 
0x0000000000400940 in binary_search (
    directory=<error reading variable: Cannot access memory at address 0x7fffff7feff8>, 
    key=<error reading variable: Cannot access memory at address 0x7fffff7feff0>, l=<error reading variable: Cannot access memory at address 0x7fffff7fefec>, 
    r=<error reading variable: Cannot access memory at address 0x7fffff7fefe8>) 
    at A2_Phase2.c:19 
19 int binary_search(Cdir directory[], char *key, int l, int r) { 

謝謝!

+0

您不應該爲此輸入malloc – Eregrith

+0

這是爲什麼?很想知道。 – user2004672

+0

http://stackoverflow.com/questions/605845 – Eregrith

回答

4
int COUNTRY_COUNT = atoi(argv[1]); 

讀取的國家數量作爲參數傳遞給程序,但你後來硬編碼的假設,這是>= 238當你調用

binary_search(directory, "ZWE", 0, 238); 

你可以嘗試

binary_search(directory, "ZWE", 0, COUNTRY_COUNT-1); 

代替?也有你的binary_search功能很少的錯誤,可以重新寫爲

int binary_search(Cdir directory[], const char *key, int l, int r) 
{ 
    int mid = (r + l)/2; 
    int cmp = strncmp(key, directory[mid].code, 3); 
    if (l >= r) { 
     if (cmp == 0) 
      return l; 
     return -1; 
    } 
    if (cmp < 0) 
     return binary_search(directory, key, l, mid - 1); 
    else if (cmp > 0) 
     return binary_search(directory, key, mid + 1, r); 
    else 
     return mid; 
} 

主要變化

  • mid計算考慮l以及r
  • (如基裏連科指出)認識到它可能找不到匹配。在此情況下返回-1
  • 將呼叫數減少到strcmp。很輕微,但它使代碼更清晰,我和會改善搜索

的性能同樣重要的是,有使你的代碼難以閱讀的內部函數不必要的空白的

  • 羣衆的一些風格問題
  • 對於變量使用大寫字母(例如COUNTRY_COUNT)是不尋常的。所有大寫字母通常都是非正式保留的,用變量使用lower或camel來定義
+0

謝謝你的所有建議。我確實應用了它們,儘管我仍然得到了與調用binary_search函數時發生的segfault相同的segfault,而不是在它之內。 – user2004672

+0

@ user2004672在您第一次調用'binary_search'或者在很長的調用鏈結束時會發生段錯誤嗎?如果它發生在一個長鏈的末尾,那麼您可能會溢出堆棧,這表示二進制搜索算法不正確。 – simonc

+0

@ user2004672這也是值得檢查的,你已經精確地遵循了所有建議。我懷疑你沒有完全按照我的代碼 - 我只注意到它不會編譯。 (現在已經修復) – simonc

0

在遞歸函數中,如果沒有匹配的元素,我看不到任何結尾情況。

1
int mid = (int) r/2; 

真的嗎?我想你會發現那不是中點。另外,正如其他地方所指出的,如果沒有找到該值,則不存在終止情況。您需要考慮遞歸如何適用於不同的輸入,包括無效輸入。

我會做這樣的事情:

int binary_search(Cdir directory[], char *key, int l, int r) 
{ 
    int mid = (l+r)/2; 
    int c = strncmp(key, directory[mid].code, 3); 

    if(c == 0) return mid; 
    if(l>=r) return -1; 

    if (c < 0) 
     return binary_search(directory, key, l, mid - 1); 

    return binary_search(directory, key, mid + 1, r); 
} 

同樣在此:

char filename[] = "RandomStructDir.bin"; 

fd = open(filename, O_RDONLY, S_IRWXU); 
if (fd < 0) 
    perror(strcat(filename, " failed to open.")); 

filename[]是在堆棧上的固定長度的數組。發生錯誤時,您嘗試連接到它。這可能會導致更嚴重的錯誤,因爲它是未定義的行爲 - 你正在摧毀堆棧。

+0

謝謝,這個知識非常有用。有趣的是,我的教授提供了這個錯誤處理的例子...... – user2004672

+0

@ user2004672編寫'perror(strcat(文件名,「無法訪問。」));'是白癡,教授或沒有教授。 –

0

我的堆棧幀惡化

看起來非常像你聲明的變量是堆棧太大。代替

int largeArray[1000][1000]; 

聲明它作爲一個指針

int *largeArray[1000][1000]; 

在代碼過程變化是必要的。

相關問題