2015-05-28 2 views
5

Я пытаюсь проверить этот код файла test.c ниже с помощью Valgrind, когда я делаю Gcc test.c -o тест я получаю ошибку последующейValgrind ошибка 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) 

, но когда я запускаю GCC test.c -o test, а затем valgrind. Я не получаю никаких ошибок. Мой вопрос: что произойдет с valgrind в этом случае? Есть ли способ запустить valgrind для 32 или 64 бит?

#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 Но проблема возникает, когда я пытаюсь прочитать файл. Я редактировал мой код выше. Я получаю Ошибка чтения файлаError чтение файлаError чтения

+0

Ваш код не читается, пожалуйста, отформатируйте его. И 'sizeof (char) == 1' по определению. –

+1

Ваш «Ошибка чтения файла», появляющийся 3 раза, должен означать, что в файле ничего не записано *, или вы пишете в файл и сразу же пытаетесь его прочитать. – usr2564301

+0

в функции: node_read() и в функции: node_write(): каждая из этих функций имеет переменную в стеке: 'i', которая не используется. Предложите 1) удалить эти две переменные. 2) включить все предупреждения при компиляции и исправить эти предупреждения (после этого компилятор знает язык C намного лучше, чем вы или я). – user3629249

ответ

6

Valgrind право беспокоиться. В этой строке

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

Вы пишете 1 байт больше данных, чем разрешено; один за пределами вашей новой временной строки стека. Вы, вероятно, путают написание строки (с +1 для завершающего нуля) с записью в точности (максимальный) размер буфера используется:

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

Поскольку вы демпинг содержимое памяти в файл, вы правильно очистить строку память перед использованием sprintf. Вы никогда не знаете, что внутри свежей выделенной памяти!
Обратите внимание, что если вас беспокоит целостность данных, всегда лучше использовать безопасный вариант sprintf_s, так как он будет защищать вас от чрезмерного запуска этого буфера.

+1

, но я хочу написать фиксированный массив длины newid – Juan

+0

@Juan: справедливая точка (и я был интересно, как вы прочтете эту строку!). Перевернутый мой ответ и +1 для вас для очистки строки перед записью на диск. Но загляните в функции '_s' для обеспечения безопасности. Также используйте ALL_CAPS для '# define' - это соглашение, но довольно сильное. – usr2564301

+0

Я редактирую свой вопрос ... – Juan

Смежные вопросы