2016-04-13 39 views
2

編輯:感謝repliers我已經改變了FREAD至(......的sizeof緩衝,1,...),但現在我得到這個錯誤的valgrind:爲什麼這個緩衝區指向不可尋址的字節?

==2409== Invalid read of size 4 
==2409== at 0x51AB8D0: fread (iofread.c:41) 
==2409== by 0x4007B6: main (recover2.c:31) 
==2409== Address 0x5502000 is not stack'd, malloc'd or (recently) free'd 
==2409== 
==2409== Use of uninitialised value of size 8 
==2409== at 0x51B8787: _IO_sgetn (genops.c:495) 
==2409== by 0x51AB93E: fread (iofread.c:42) 
==2409== by 0x4007B6: main (recover2.c:31) 
==2409== 
==2409== Invalid read of size 8 
==2409== at 0x51B8787: _IO_sgetn (genops.c:495) 
==2409== by 0x51AB93E: fread (iofread.c:42) 
==2409== by 0x4007B6: main (recover2.c:31) 
==2409== Address 0x40 is not stack'd, malloc'd or (recently) free'd 
==2409== 
==2409== 
==2409== Process terminating with default action of signal 11 (SIGSEGV) 
==2409== Access not within mapped region at address 0x40 
==2409== at 0x51B8787: _IO_sgetn (genops.c:495) 
==2409== by 0x51AB93E: fread (iofread.c:42) 
==2409== by 0x4007B6: main (recover2.c:31) 
==2409== If you believe this happened as a result of a stack 
==2409== overflow in your program's main thread (unlikely but 
==2409== possible), you can try to increase the size of the 
==2409== main thread stack using the --main-stacksize= flag. 
==2409== The main thread stack size used in this run was 8388608. 

我是新來的所以我希望這是有道理的。我正在編寫此代碼以從文件中檢索數據並將其複製到jpeg文件。該代碼旨在通過其標題找到一個jpg文件,然後將其寫入文件。該代碼是:

#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 
#include <string.h> 

int main(int argc, char* argv[]) 
{ 

FILE* file = fopen("card.raw", "r"); 
if (file == NULL) 
{ 
    printf("Could not open file!\n"); 
    return 1; 
} 

char title[7]; 
int currentImage = 0; 
uint8_t buffer[512]; 
FILE* img; 
while (fread(buffer, sizeof(buffer), 512, file) == 1) 
{ 
printf("found data!\n"); 
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff) 
{ 
    if (buffer[3] == 0xe0 || buffer[3] == 0xe1 || buffer[3] == 0xe2 || buffer[3] == 0xe3 || buffer[3] == 0xe4 || buffer[3] == 0xe5 || buffer[3] == 0xe6 || buffer[3] == 0xe7 || buffer[3] == 0xe8 || buffer[3] == 0xe9 || buffer[3] == 0xea || buffer[3] == 0xeb || buffer[3] == 0xec || buffer[3] == 0xed || buffer[3] == 0xee || buffer[3] == 0xef) 
    { 
     printf("Found new jpg!\n"); 
     sprintf(title, "%03d.jpg", currentImage); 
     img = fopen(title, "a"); 
     currentImage++; 
     printf("size of buffer to print is %lu\n", sizeof(buffer)); 
     fwrite(buffer, sizeof(buffer), 1, img); 
     } 
} 
else if (currentImage > 0) 
{ 
     fwrite(buffer, sizeof(buffer), 1, img); 


} 

} 
} 

我得到一個分段錯誤,一旦發現有JPEG,並執行FWRITE,然後返回到while循環。

的Valgrind的錯誤是:

==1866== Syscall param read(buf) points to unaddressable byte(s) 
==1866== at 0x5228810: __read_nocancel (syscall-template.S:81) 
==1866== by 0x51B63B8: _IO_file_xsgetn (fileops.c:1438) 
==1866== by 0x51AB93E: fread (iofread.c:42) 
==1866== by 0x4007C3: main (recover2.c:31) 
==1866== Address 0xfff001000 is not stack'd, malloc'd or (recently) free'd 
==1866== 
==1866== Jump to the invalid address stated on the next line 
==1866== at 0x0: ??? 
==1866== Address 0x0 is not stack'd, malloc'd or (recently) free'd 
==1866== 
==1866== 
==1866== Process terminating with default action of signal 11 (SIGSEGV) 
==1866== Bad permissions for mapped region at address 0x0 
==1866== at 0x0: ??? 

我是新來這使仍在學習和記憶等,因此在理解它爲什麼出了錯任何幫助,將不勝感激。

+0

得到答案後,請注意不要大幅改變您的問題。無論如何,你正在打印8個字符到'title',它只能容納7個。 – usr2564301

+0

Thanks @ rad-lexus! – edd91

回答

6

通過這樣做

fread(buffer, sizeof(buffer), 512, file) 

你問fread閱讀512塊,每塊是sizeof(buffer)字節長。即您正嘗試將512 * 512 = 262144字節讀入聲明爲uint8_t buffer[512]的數組中。這當然不適合。

如果你只是想將數據讀入buffer陣列,這將是要麼

fread(buffer, sizeof buffer, 1, file) 

fread(buffer, 1, sizeof buffer, file) 

,或者,如果你願意的話,根據

fread(buffer, sizeof *buffer, sizeof buffer/sizeof *buffer, file) 

讀取操作中您認爲是「原子」數據塊。


另外

sprintf(title, "%03d.jpg", currentImage); 

將產生至少7個字符長的字符串(例如001.jpg),這意味着title必須是長,以容納零終止至少8個字符。但是,您的title被宣佈爲

char title[7]; 

這太小了。

+0

嗨AnT,謝謝你指出這個錯誤。我已經將它更改爲fread(buffer,sizeof buffer,1,file),但不幸的是我仍然遇到了分段錯誤。 – edd91

+0

嗨AnT,我已經在我的原帖中包含了新的valgrind錯誤。謝謝 – edd91

+0

@ edd91:您的代碼不完整,無法完全分析。但是,正如我在上面添加的,你的'標題'需要更大。 – AnT

1

作爲每fread()man page,簽名是

size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream);

所述描述是

功能fread()讀取數據的nmemb元素,每個size字節長,來自指向的流210,將它們存儲在ptr給出的位置。

所以,你的代碼應該是

while (fread(buffer, sizeof(buffer[0]), 512, file) == 1) 

否則,你就結束了要求讀取和存儲512個數每個大小的塊,512個字節的,這是錯誤的,會導致緩衝區溢出,如valgrind報告。