簡體   English   中英

C - 分段錯誤將char指針傳遞給函數

[英]C - Segmentation fault passing char pointer to a function

當我調用一個數組來標記無符號整數集[9]中相應位位的位位置時,我得到一個分段錯誤,其索引在全局名稱數組名[320] [30]中。 當我運行程序時,我使用./a.out <data.dat並在列表中加載320個單詞的列表。 沒有超過30個字符。

另外, typedef unsinged int Set[10];

這是我調用addName2Set函數的代碼

//add name to unsigned int set
void addName2Set(Set set, char *key){
    int index;

    //binary search to get index for key
    index = binarySearch(names, key, 0, 319);
    //call add2set to add index to set
    add2Set(set, index);
}

這是add2Set

//add value passed to set passed
void add2Set(Set set, int index){
  int element, position;

  //find which element, set[element] of set index is in
  element = findArrayElement(index);

  //convert index to bit position 0-31 in set[element]
  position = findElementPos(element, index);

  //in set[element], set bit position 'position' to 1
  set[element] = set[element] | (1 << position);
}

這是findArrayElement和findElementPos函數

//for unsigned int set[i], return i
int findArrayElement(int index){
  //index range [j,i]
  int i;
  int j=0;
  //element in set array
  int element;

  //loop through [j,i], return element if range true
  for(i=31; i<320; i+=32){
    if(i <= i && index >= j){       
      return element;
    }
    j+=32;
    element++;
  }
}

//find bit position 0-31 corresponding to index
int findElementPos(int element, int index){
    int j;
    int position;

    j = element*32;
    position = index - j + 1;

    //return bit position
    return position;
}

最后這里是我調用addName2Member函數的地方

//declare key pointer
char *key = (char*)malloc(30);

//set search word to pointer key
strcpy(key, "clean");

//addName2Set
addName2Set(set1,key);

任何人都知道為什么我運行程序時會出現分段錯誤? “Clean”是data.dat列表中的第一個單詞。

以下是valgrind的結果

== 1645 ==讀取大小4無效

== 1645 ==在0x8048860:add2Set(set.c:61)

== 1645 == by 0x8048A5D:addName2Set(set.c:145)

== 1645 == by 0x80485D2:main(driver.c:29)

== 1645 ==地址0x9DBED860沒有堆疊,malloc'd或(最近)免費

== == 1645

== 1645 ==使用信號11(SIGSEGV)的默認操作終止進程

== 1645 == GPF(指針超出范圍?)

== 1645 ==在0x8048860:add2Set(set.c:61)

== 1645 == by 0x8048A5D:addName2Set(set.c:145)

== 1645 == by 0x80485D2:main(driver.c:29)

沒有看到整個程序(包括findArrayElement()findElementPos()的定義,很難說。

您可以使用強力方法並在GDB中運行該程序:

gdb ./a.out

並從GDB shell中調用

run < data.dat

當segfault發生時,程序將在調試器中停止。 然后你可以打電話

bt

要查看程序中segfault的確切位置。

看起來你在findArrayElement的末尾缺少一個return語句。 這可能就是你的問題。

在OP更正了findArrayElement並在結尾return -1之后:

請注意,您還需要檢查findArrayElement返回的-1,否則您可能會對set數組進行索引。

更新:關閉return語句導致OP問題的確切原因是函數承諾返回一個整數(它的返回類型是int ),所以當沒有return語句來設置返回值時,內存/將存儲返回值的寄存器將包含“垃圾”(當時在內存/寄存器中發生的任何事情)。 發生了seg.fault,因為垃圾“返回值”導致索引到數組中以訪問不屬於應用程序的元素。 這種行為是不穩定的,因為它取決於“垃圾”恰好是什么值(它甚至可能是在有效結果范圍內的值),因此在某些情況下很難找到。

我知道防止此類錯誤發生的最佳方法是將編譯器的警告級別設置為高,因此它會發出關於缺少return語句的警告,並且還可能將編譯器設置為將所有警告轉換為錯誤 - 警告通常描述問題應該解決,以避免可能的不良行為。 如果存在程序員知道不是問題的某個警告,則可以配置編譯器(可能通過預處理器語句,盡管這不是可移植的方法,因為它依賴於編譯器)來忽略這些特定警告。

如果你的程序命名為a.out。 然后,使用像valgrind這樣的valgrind --tool=memcheck a.out < data.dat然后valgrind會在一個特殊的memory運行你的程序,它會告訴你哪里出錯了。 不要忘記使用gcc -g將調試信息添加到bin文件中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM