2015-05-28 20 views
5

Tôi đang cố gắng để xác minh test.c tập tin mã này dưới đây sử dụng valgrind, khi tôi thực hiện kiểm tra gcc test.c -o Tôi nhận được lỗi sauValgrind lỗi M64 m32

Syscall param write(buf) points to uninitialised byte(s) 
==22765== at 0x4F22870: __write_nocancel (syscall-template.S:81) 
==22765== by 0x4EB0002: [email protected]@GLIBC_2.2.5 (fileops.c:1261) 
==22765== by 0x4EB14DB: [email protected]@GLIBC_2.2.5 (fileops.c:538) 
==22765== by 0x4EB0D5F: [email protected]@GLIBC_2.2.5 (fileops.c:165) 
==22765== by 0x4EA4B0F: [email protected]@GLIBC_2.2.5 (iofclose.c:59) 
==22765== by 0x400986: main (in /home/grados-sanchez/git/merkle-codigos-C/test) 
==22765== Address 0x4025770 is not stack'd, malloc'd or (recently) free'd 
==22765== Uninitialised value was created by a stack allocation 
==22765== at 0x4007E2: node_write (in /home/grados-sanchez/git/merkle-codigos-C/test) 

nhưng khi tôi chạy gcc test.c -o kiểm tra và sau đó valgrind tôi không nhận được bất kỳ lỗi nào. Câu hỏi của tôi là Điều gì xảy ra với valgrind trong trường hợp này? Có cách nào để chạy valgrind cho 32 hoặc 64 bit?

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

#define id_lenght 6000 
typedef unsigned char * ustring; 
typedef struct { 
    ustring ustr; 
    int height; 
    char id[id_lenght]; 
} node; 

int validation_read(void * ptr_var, size_t sizeof_datatype, int num, 
    FILE * ptr_file) { 
    if (fread(ptr_var, sizeof_datatype, num, ptr_file) <= 0) { 
     printf("Error reading file"); 
     return 1; 
    } 
return 0; 
} 

void node_read(FILE * node_ptr, node * n, int r) { 
    int i; 
    validation_read(n->id, sizeof(unsigned char), id_lenght, node_ptr); 
    validation_read(&(n->height), sizeof(int), 1, node_ptr); 
    validation_read(n->ustr, sizeof(unsigned char) * (r + 1), 1,node_ptr); 
} 

void node_init(node * n, int r) { 
    memset(n, 0, sizeof(node)); 
    n->ustr = malloc((r + 1) * sizeof(unsigned char)); 
    memset(n->ustr, 0, (r + 1)); 
    n->ustr[r] = 0; 
    n->height = -1; 
    memset(n->id,0,id_lenght+1); 
} 


void node_write(FILE * node_ptr, node * n, int r) { 
    int i; 
    char newid[id_lenght]; 
    memset(newid,0,id_lenght); 
    sprintf(newid,"%s",n->id); 
    fwrite(newid, sizeof(char), id_lenght+1, node_ptr); 
    fwrite(&(n->height), sizeof(int), 1, node_ptr); 
    fwrite(n->ustr, sizeof(unsigned char) * (r + 1), 1,node_ptr); 
} 


void node_destroy(node * n) { 
    free(n->ustr); 
    n->height = -1; 
} 

int main(){ 
    FILE * ptr = fopen("juantest","w+"); 
    int r = 64/8; 
    node in; 
    node_init(&in, r); 
    node_write(ptr, &in, r); 
    node_destroy(&in); 
    fclose(ptr); 
} 

EDIT Tuy nhiên, một vấn đề xảy ra khi tôi cố gắng để đọc các tập tin. Tôi đã chỉnh sửa mã trên của mình. Tôi gặp lỗi khi đọc tệpMỗi tệp đọcError đọc

+0

Mã của bạn không thể đọc được, vui lòng định dạng mã.! Và 'sizeof (char) == 1' theo định nghĩa. –

+1

"Lỗi đọc tệp" của bạn xuất hiện 3 lần phải có nghĩa là không có gì * được viết * trong tệp hoặc bạn đang ghi vào tệp và ngay lập tức cố gắng đọc từ tệp đó. – usr2564301

+0

trong hàm: node_read() và trong hàm: node_write(): mỗi hàm này có một biến trên ngăn xếp: 'i' không được sử dụng. Đề xuất 1) xóa hai biến đó. 2) cho phép tất cả các cảnh báo khi biên dịch và sửa các cảnh báo đó (afterall, trình biên dịch biết ngôn ngữ C tốt hơn rất nhiều so với bạn hoặc tôi.) – user3629249

Trả lời

6

Valgrind là điều phải lo lắng. Trong dòng này

fwrite(newid, sizeof(char), id_lenght+1, node_ptr); 

bạn đang ghi nhiều hơn 1 byte dữ liệu; số vượt quá chuỗi ngăn xếp tạm thời mới của bạn. Bạn có thể nhầm lẫn viết một chuỗi (với một +1 cho chấm dứt zero) với văn bản chính xác (tối đa) kích thước bộ đệm được sử dụng:

fwrite(newid, sizeof(char), id_length, node_ptr); 

Vì bạn đang bán phá giá nội dung bộ nhớ vào một tập tin, bạn là chính xác để xóa các chuỗi bộ nhớ trước khi sử dụng sprintf. Bạn không bao giờ biết những gì bên trong bộ nhớ được cấp phát mới!
Lưu ý rằng nếu bạn lo lắng về tính toàn vẹn của dữ liệu, tốt hơn hết nên sử dụng biến thể an toàn sprintf_s thay thế, vì nó sẽ bảo vệ bạn khỏi việc chạy bộ đệm này.

+1

nhưng tôi muốn viết một mảng chiều dài cố định newid – Juan

+0

@Juan: điểm công bằng (và tôi đã tự hỏi làm thế nào bạn sẽ đọc chuỗi đó trở lại!). Đảo ngược câu trả lời của tôi và +1 cho bạn để xóa chuỗi trước khi ghi vào đĩa. Nhưng hãy nhìn vào các hàm '_s' cho an toàn. Ngoài ra hãy sử dụng ALL_CAPS cho '# define' - đó là một quy ước nhưng là một quy ước khá mạnh mẽ. – usr2564301

+0

Tôi chỉnh sửa câu hỏi của mình ... – Juan

Các vấn đề liên quan