2014-11-08 108 views
0

今天晚上我一直在玩下面的代碼幾個小時,我只是用它抓撓我的腦袋。無效的讀取大小8,無效的寫入大小8(Valgrind)

當使用函數從標準輸入填充數組時,我總是收到「無效的8號大小寫」和「大小8的無效讀取」。

任何幫助將不勝感激......我知道堆棧溢出有很多這些錯誤,但其中大多數是唯一的情況。

void RawScore(unsigned int rawScoreCount, unsigned int numStudents, student studentInfo[], 
       unsigned int projectCount, double rawScores[], double scores[], double weights[]) 
{ 
    int id; 

    for (int i = 0; i < rawScoreCount; i++) 
    { 
     std::cin >> id; 

     for (int j = 0; j < numStudents; j++) 
     { 
      if (id == studentInfo[j].id) 
      { 
       for (int k = 0; k < projectCount; k++) 
       { 
        std::cin >> rawScores[k]; 
        studentInfo[j].score += rawScores[k]/scores[k] * weights[k]; 
       } 
      } 
     } 
      std::cin.ignore(10000, '\n'); 
    } 
} 

從MEMCHECK下面的錯誤是:

==5793== Memcheck, a memory error detector 
==5793== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==5793== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info 
==5793== Command: a.out.app 
==5793== 
==5793== Invalid write of size 8 
==5793== at 0x40E54DB: std::__1::istreambuf_iterator<char, std::__1::char_traits<char> > std::__1::num_get<char, std::__1::istreambuf_iterator<char, std::__1::char_traits<char> > >::__do_get_floating_point<double>(std::__1::istreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::istreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::ios_base&, unsigned int&, double&) const (in /usr/lib/i386-linux-gnu/libc++.so.1.0) 
==5793== by 0x40E517E: std::__1::num_get<char, std::__1::istreambuf_iterator<char, std::__1::char_traits<char> > >::do_get(std::__1::istreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::istreambuf_iterator<char, std::__1::char_traits<char> >, std::__1::ios_base&, unsigned int&, double&) const (in /usr/lib/i386-linux-gnu/libc++.so.1.0) 
==5793== by 0x804D0FA: std::__1::basic_istream<char, std::__1::char_traits<char> >::operator>>(double&) (locale:771) 
==5793== by 0x804CECC: RawScore(unsigned int, unsigned int, student*, unsigned int, double*, double*, double*) (input.cpp:44) 
==5793== by 0x804EE6A: main (main.cpp:35) 
==5793== Address 0x445c388 is 0 bytes after a block of size 40 alloc'd 
==5793== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==5793== by 0x40BA709: operator new(unsigned int) (in /usr/lib/i386-linux-gnu/libc++.so.1.0) 
==5793== by 0x804EE26: main (main.cpp:32) 
==5793== 
==5793== Invalid read of size 8 
==5793== at 0x804CED3: RawScore(unsigned int, unsigned int, student*, unsigned int, double*, double*, double*) (input.cpp:49) 
==5793== by 0x804EE6A: main (main.cpp:35) 
==5793== Address 0x445c388 is 0 bytes after a block of size 40 alloc'd 
==5793== at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==5793== by 0x40BA709: operator new(unsigned int) (in /usr/lib/i386-linux-gnu/libc++.so.1.0) 
==5793== by 0x804EE26: main (main.cpp:32) 
==5793== 
....... output of program here ...... 
==5793== 
==5793== HEAP SUMMARY: 
==5793==  in use at exit: 0 bytes in 0 blocks 
==5793== total heap usage: 9 allocs, 9 frees, 476 bytes allocated 
==5793== 
==5793== All heap blocks were freed -- no leaks are possible 
==5793== 
==5793== For counts of detected and suppressed errors, rerun with: -v 
==5793== ERROR SUMMARY: 20 errors from 2 contexts (suppressed: 0 from 0) 

我已經縮小的問題,下面兩行,在讀10個錯誤的寫入和10:

std::cin >> rawScores[k]; 
studentInfo[j].score += rawScores[k]/scores[k] * weights[k]; 

任何有識之士將不勝感激!

+0

PLZ提供main(),輸入參數或兩者,如果可能的話。 – 2014-11-08 05:18:23

回答

1
std::cin >> rawScores[k]; 
studentInfo[j].score += rawScores[k]/scores[k] * weights[k]; 

從你上面的程序jk取決於用戶輸入的,因此它們的值可以超越實際陣列的studentInforawScores指數。

你的程序應該有邏輯,以便它的程序不訪問數組邊界。

您可以監視您的程序

$ valgrind --tool=memcheck --db-attach=yes ./a.out 

有關這一概念,並詳細信息,如何使用它,您可以參考下面的帖子:

https://stackoverflow.com/a/22658693/2724703

+0

輸出結果沒有顯示任何內容。我也在VS調試器上運行這個,並且看不到它出界。 – Sterling 2014-11-08 05:37:07

+0

不受限制的訪問具有未定義的行爲,因此有時它不會立即出現在程序中。但valgrind報告可以證明您的程序無法訪問債券。您可以參考上述建議的步驟,並在錯誤點進行現場調試。你可以在那個時候驗證所有變量和源輸入狀態。 – 2014-11-08 05:42:15

+0

謝謝!你是對的 - 我玩弄了定義/聲明並做了這個:double * rawScores = new double [rawScoreCount + 2]; 對我來說C++是相當新的 - 如果有什麼東西碰到了界限,我一直習慣於一個很好的崩潰! – Sterling 2014-11-08 06:01:32

1

你分配rawScores正常嗎?

你還需要確保projectCount比rawScores大小

0
  1. 檢查是否已分配足夠的內存數組下[rawScores, 得分,權重,studentInfo]你傳遞給這個函數之前。
  2. 檢查用戶輸入,應該在數組範圍內。

它會切切實實解決您的問題

0

數組邊界溢出是陰險。在C++中,如果你不損害你關心的某些東西,你可能永遠不會發現你重蹈覆轍......除了你的某些值可能不是很正確。 (這是「錯誤」在很多病毒攻擊的核心 - 以寫得不好的節目,使有關緩衝區/數組大小的假設優勢

比方說,你有這樣的事情:

char buffer[50]; 
    char author[] = "My Name"; 

    cout << author; 
    cin >> buffer; 

如果我輸入一個20個字符的輸入字符串,沒有傷害,沒有犯規。

如果我鍵入一個55個字符的輸入字符串,「我的名字」將被部分覆蓋,除非我嘗試重新轉載作者,否則沒有人會注意到。直到許多(許多)陳述後面纔會發生。當你看到作者,也許它看起來像「1234ame」,你會問「從哪裏來的?」

更糟糕的是,如果我輸入一個70個字符的輸入字符串,我會垃圾作者,和無論它來自什麼,可能是內存管理控制塊,I/O緩衝區等,也許這將是「明顯」(或不)。直到很長時間後,如果有的話,「沒有失敗」可能並不意味着「正確」,所以你對「輸出不顯示任何越界」的評論可能並不如你所期望的那樣令人欣慰。早些時候 - 仔細注意你的陣列,兩個分配一個填充。

如果這不是您需要的答案,那麼您需要顯示數組的定義以及它們是如何創建的。