2013-10-20 233 views
2

UPDATE創建:內存泄漏被殺,現在我需要知道我可以初始化此聲明:Valgrind的:未初始化值是由堆分配

vector *addorsub = (vector*)malloc(sizeof(*addorsub)); 

這是我從Valgrind的獲得:

[email protected]:~/Escritorio/valgrind/vg$ valgrind --tool=memcheck --leak-check=full --track-origins=yes ./eda.exe 
==6129== Memcheck, a memory error detector 
==6129== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. 
==6129== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info 
==6129== Command: ./eda.exe 
==6129== 
==6129== Conditional jump or move depends on uninitialised value(s) 
==6129== at 0x4C2A7E4: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6129== by 0x4015E7: destroy_vector(vector*) (metbasicos.c:17) 
==6129== by 0x4014E2: main (main.c:175) 
==6129== Uninitialised value was created by a heap allocation 
==6129== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==6129== by 0x400D59: main (main.c:87) 
==6129== 
==6129== 
==6129== HEAP SUMMARY: 
==6129==  in use at exit: 0 bytes in 0 blocks 
==6129== total heap usage: 2 allocs, 2 frees, 16 bytes allocated 
==6129== 
==6129== All heap blocks were freed -- no leaks are possible 
==6129== 
==6129== For counts of detected and suppressed errors, rerun with: -v 
==6129== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2) 

這是主程序:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 
#include "metbasicos.h" 
#include "metintermedios.h" 
#include "metavanzados.h" 




//NumsVector, funcion que nos devuelve el numero de "numeros" que hay en cada vector del .txt, 
//es decir, los n floats por cada vector 

int NumsVector(char *linea, int size){ 
    int numsvector = 1; //Inicializamos a 1 ya que no podemos suponer valor maximo segun enunciado, pero si minimo >= 1 
    int n; 
    for(n = 2; n<= size; n++){ //como ya suponemos que el primer valor despues del corchete es un numero y ya lo hemos contado, empezamos en 2 
     if (linea[n] != '[' && linea[n] != ']'){ 
      if(linea[n] == 44){ 
       numsvector = numsvector + 1; 
      } 
     } 
    } 
    return numsvector; 
} 

    int main(){ 
    int n =0, i = 0; 
    scanf("%d\n", &n); 
    vector **v = (vector **)malloc(sizeof(vector*) * n); 
    for(i = 0; i<n; ++i) { 
     char *line = NULL, ch; 
     int it = 0 ; 
     line = (char*) malloc (2*sizeof(char)) ; 
     *line = '\0' ; 
     while((ch=getchar()) != '\n') 
     { 
     *(line+it) = ch ; 
     it++ ; 
     line = (char*) realloc(line, (2*sizeof(char)) + it) ; 
     } 
     *(line+it) = '\0'; 
     int read = strlen(line); 
     int numsvector = NumsVector(line, read); 
     float* nfloat; //sabemos el tamanyo del vector que hemos leido, creamos array de floats y lo llenamos de los floats 
     //empieza el proceso para obtener los floats a partir de string de chars 
     nfloat = (float*)malloc(numsvector*sizeof(float)); 
     int j = 0; 
     line[strlen(line)] = ','; /* Replaces the end ] with a , */ 
     char *p = line + 1; /* creates a new pointer, pointing after the first [ in the original string */ 
     do 
     { 
      sscanf(p, "%f,", &nfloat[j]); /* grabs up to the next comma as a float */  
      while (*(p++) != ',') ; /* moves pointer forward to next comma */ 
     } 
     while (++j < numsvector); /* stops when you've got the expected number */  
     v[i] = create_vector(numsvector, nfloat);//conseguimos almacenar el contenido del string en un vector del tipo float (nfloat) 
     int aux; 
     for(aux = 0; aux<numsvector; ++aux){ //test de que cada elemento se ha guardado bien y printa todos los elementos ok 
      printf("V[%d]->data[%d] = : %.1f\n", i, aux, v[i]->data[aux]); //test de que la memoria se almacena bien, luego se borra 
     } 
     free(line); 
     free(nfloat); 
    } 
    char mystring [21]; 
    char str[10], charv1[6], charv2[6]; 
    int operation = 0; 
    char simbol[4]; /* Can be +, - and dot */ 
    mystring[0] = str[0] = charv1[0] = charv2[0] = simbol[0] = 'a'; 
    for(i = 0; i<21; i++){ 
     mystring[i] = 'a'; 
    } 
    for(i = 0; i<6; i++) 
    { 
     charv1[i] = 'a'; 
     charv2[i] = 'a'; 
    } 
    for (i = 0; i < 10; i++) 
    { 
      str[i] = 'a'; 
    } 
    for (i = 0; i < 4; i++) 
    { 
      simbol[i] = 'a'; 
    } 
    vector *addorsub = (vector*)malloc(sizeof(*addorsub)); 
    fgets (mystring , 21 , stdin); 
    do { 
     sscanf (mystring,"%s",str); 
     int res = strlen (str); 
     //int res = strncmp(str, "incr", 10); 
     if(mystring[0] == 'p') operation = 1; 
     else if(mystring[0] == 'i') operation = 2; 
     else if(mystring[0] == 'd' && mystring[1] == 'i') operation = 4; 
     else if(mystring[0] == 'd' && mystring[1] == 'e') operation = 5; 
     else if(res == 9) operation = 6; 
     else if(res == 4 && mystring[0] == 'n') operation = 7; 
     else{ 
      sscanf (mystring,"%s %s",str, simbol); 
      if (simbol[0] == '+') operation = 8; 
      else if(simbol[0] == '-') operation = 9; 
      else operation = 3; 
     } 
     int v1 = 0, v2 = 0; 
     float returnresult = 0.0; 
     switch(operation) 
     { 
     case 1 : 
      sscanf (mystring,"%s %s",str, charv1); 
      v1 = strtol((charv1+1) , NULL , 10); 
      printf("PRINT: %d\n", v1); 
      print(v[v1-1]); 
      break; 
     case 2 : 
      sscanf (mystring,"%s %s %s",str, charv1, charv2); 
      v1 = strtol((charv1+1) , NULL , 10); 
      v2 = strtol((charv2+1) , NULL , 10); 
      printf("INCREASE: %d %d\n", v1, v2); 
      incr(v[v1-1], v[v2-1]); 
      break; 
     case 3 : 
      sscanf (mystring,"%s %s %s",charv1, str, charv2); 
      v1 = strtol((charv1+1) , NULL , 10); 
      v2 = strtol((charv2+1) , NULL , 10); 
      returnresult = dot(v[v1-1], v[v2-1]); 
      printf("DOT: %d %d\n", v1, v2); 
      printf("%f\n", returnresult); 
      break; 
     case 4 : 
      sscanf (mystring,"%s %s %s", str, charv1, charv2); 
      v1 = strtol((charv1+1) , NULL , 10); 
      v2 = strtol((charv2+1) , NULL , 10); 
      returnresult = distance(v[v1-1], v[v2-1]); 
      printf("%f\n", returnresult); 
      break; 
     case 5 : 
      sscanf (mystring,"%s %s %s",str, charv1, charv2); 
      v1 = strtol((charv1+1) , NULL , 10); 
      v2 = strtol((charv2+1) , NULL , 10); 
      decr(v[v1-1], v[v2-1]); 
      break; 
     case 6 : 
      sscanf (mystring,"%s %s",str, charv1); 
      v1 = strtol((charv1+1) , NULL , 10); 
      normalize(v[v1-1]); 
      break; 
     case 7 : 
      sscanf (mystring,"%s %s",str, charv1); 
      v1 = strtol((charv1+1) , NULL , 10); 
      returnresult = norm(v[v1-1]); 
      printf("%f\n", returnresult); 
      break; 
     case 8 : //suma 
      sscanf (mystring,"%s %s %s", charv1, str, charv2); 
      v1 = strtol((charv1+1) , NULL , 10); 
      v2 = strtol((charv2+1) , NULL , 10); 
      addorsub = add(v[v1-1], v[v2-1]); 
      printf("SUMA: %d %d\n", v1, v2); 
      print(addorsub); 
      break; 
     case 9 : 
      sscanf (mystring,"%s %s %s", charv1, str, charv2); 
      v1 = strtol((charv1+1) , NULL , 10); 
      v2 = strtol((charv2+1) , NULL , 10); 
      addorsub = sub(v[v1-1], v[v2-1]); 
      printf("resta: %d %d\n", v1, v2); 
      print(addorsub); 
      break;  
     default : 
      printf("operation value is: %d\n", operation); 
      break; 
     } 
     operation = 0; 
    } while (fgets (mystring , 21 , stdin) != NULL); 
    for (i = 0; i < n; ++i) 
    { 
     destroy_vector(v[i]); 
    } 
    free(v); 
} 

我檢查了所有的malloc和釋放,但我想我留下任何.. 。

有什麼想法?非常感謝你。

編輯:

輸入例(INT .txt文件作爲標準輸入):

3 
[9.3,1.2,87.9] 
[1.0,1.0] 
[0.0,0.0,1.0] 
v1 + v2 
v3 - v1 
incr v3 v1 
decr v1 v3 
decr v1 v3 
v2 dot v3 
norm v3 
distance v1 v3 
normalize v3 
print v3 

STRUCT:

typedef struct { 
    float* data; 
    int size; 
} vector; 

metbasicos.c:

#include "metbasicos.h" 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 

/* Metodos Básicos */ 
vector *create_vector(int n, float* data){ 
    vector *newvect = (vector*)malloc(sizeof(*newvect)); 
    newvect->data = (float*)malloc(n*sizeof(float)); 
    memcpy(newvect->data, data, sizeof(float) * n); 
    newvect->size = n; 
    return newvect; 
} 

void destroy_vector(vector* v){ 
    free(v->data); 
    free(v); 
} 

void print(vector* v){ 
    int size = v->size, i; 
    for (i = 0; i < size; ++i) 
    { 
     if(i == 0) printf("[%.1f,", v->data[i]); 
     else if(i == (size-1)) printf("%.1f]\n", v->data[i]); 
     else printf("%.1f,", v->data[i]); 
    } 
} 

metintermedios .c:

#include "metintermedios.h" 
#include "metbasicos.h" 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 

/* Metodos Intermedios */ 
float dotDiferentSizes(vector* v1, vector* v2, int smax, int smin){ 
    float prod = 0.0; 
    int i; 
    for(i = 0; i < smin; i++){ 
     prod = prod + (v1->data[i])*(v2->data[i]); // += means add to product 
    } 
    for(i = smin; i < smax; i++){ 
     prod += (v1->data[i])*0; // += means add to product 
    } 
    return prod; 
} 

float dot(vector* v1, vector* v2){ 
    int smax = (v1->size), smin = 0; 
    int v1size = smax; 
    int v2size = (v2->size); 
    float product = 0.0; 
    if (v2size > smax) { 
     smax = v2size; //max_size checking 
     smin = v1size; //min_size checking 
    } 
    else if (v2size < smax){ 
      smin = v2->size; 
    } 
    else { 
     if(v1size == v2size){ 
      smin = smax; 
     } 
    } 
    // compute 
    if(smax == smin){ 
     int i; 
     for(i = 0; i < smin; i++){ 
      product += (v1->data[i])*(v2->data[i]); // += means add to product 
     } 
    } 
    else{ 
     if(v1size == smax && v1size!= smin){ 
      product = dotDiferentSizes(v1,v2,smax,smin); //v1>v2 
     } 
     if(v2size == smax && v2size!= smin){ 
      product = dotDiferentSizes(v2,v1,smax,smin); //v2>v1 OJU nomes canviem l'ordre en que posem els parametres, la funcio es identica. 
     } 
    } 
    return product; 
} 

float norm(vector* v){ 
    int size = v->size, i; 
    float norm = 0.0; 
    for(i= 0; i < size; i++){ 
     norm += (v->data[i])*(v->data[i]); 
    } 
    norm = sqrt(norm); 
    return norm; 
} 

void normalize(vector* v){ 
    int size = v->size, i; 
    float norma = 0.0; 
    norma = norm(v); 
    for(i= 0; i< size; i++){ 
     v->data[i] = v->data[i]/norma; 
    } 
    print(v); 
} 

metavanzados.c:

#include "metavanzados.h" 
#include "metintermedios.h" 
#include "metbasicos.h" 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 

/* Metodos Avanzados */ 
vector* add(vector* v1, vector* v2){ 
    vector *vadd = (vector*)malloc(sizeof(*vadd)); 
    int v1size, v2size, i; 
    v1size = v1->size; 
    int size = v1size; 
    v2size = v2->size; 
    if(v2size > v1size) { 
     size = v2size; 
     vadd = create_vector(size, v2->data); 
     for(i = 0; i < v1size; i++){ 
      vadd->data[i] += v1->data[i]; 
     } 
    } 
    else { 
     vadd = create_vector(size, v1->data); 
     for(i = 0; i < v1size; i++){ 
      vadd->data[i] += v2->data[i]; 
     } 
    } 
    return(vadd); 
    destroy_vector(vadd); 
} 

vector* sub(vector* v1, vector* v2){ 
    vector *vsub = (vector*)malloc(sizeof(*vsub)); 
    int v1size, v2size, i; 
    v1size = v1->size; 
    int size = v1size; 
    v2size = v2->size; 
    if(v2size > v1size) { 
     size = v2size; 
     vsub = create_vector(size, v2->data); 
     for(i = 0; i < v1size; i++){ 
      vsub->data[i] = v1->data[i] - vsub->data[i]; /* restamos siempre v1 - v2*/ 
     } /* en el bucle forzamos a restar v1 - v2, evitando el caso v2 - v1*/ 
     for(i = v1size; i < size; i++){ 
      vsub->data[i] = (v2->data[i])*(-1); 
     } 
    } 
    else { /* v1size >= v2size */ 
     vsub = create_vector(size, v1->data); 
     for(i = 0; i < v2size; i++){ 
      vsub->data[i] -= v2->data[i]; 
     } 
    } 
    return(vsub); 
    destroy_vector(vsub); 
} 

void incr(vector* source, vector* other){ 
    int smax, i, ssize = source->size, osize = other->size; 
    vector *vincr = (vector*)malloc(sizeof(*vincr)); 
    if(ssize > osize) smax = ssize; 
    else { 
     if(ssize < osize) smax = osize; 
     else smax = ssize; 
    } 
    vincr = add(source, other); 
    if(ssize > osize){ 
     for(i = 0; i < smax; i++){ 
      source->data[i] = vincr->data[i]; 
     } 
    } 
    else{ 
     source->data = (float*)realloc(source->data, sizeof(float) * smax); 
     source->size = smax;  
     for(i = 0; i < smax; i++){ 
      source->data[i] = vincr->data[i]; 
     } 
    } 
    print(source); 
    destroy_vector(vincr); 
} 

void decr(vector* source, vector* other){ 
    int smax, i, ssize = source->size, osize = other->size; 
    if(ssize > osize) smax = ssize; 
    else { 
     if(ssize < osize) smax = osize; 
     else smax = ssize; 
    } 
    vector *vdecr = (vector*)malloc(sizeof(*vdecr)); 
    vdecr = sub(source, other); 
    if(ssize > osize){ 
     for(i = 0; i < smax; i++){ 
      source->data[i] = vdecr->data[i]; 
     } 
    } 
    else{ 
     source->data = (float*)realloc(source->data, sizeof(float) * smax); 
     source->size = smax;  
     for(i = 0; i < smax; i++){ 
      source->data[i] = vdecr->data[i]; 
     } 
    } 
    print(source); 
    destroy_vector(vdecr); 
} 

float distance(vector* v1, vector* v2){ 
    int i; 
    float dist = 0.0; 
    vector *vdist = (vector*)malloc(sizeof(*vdist)); 
    vdist = sub(v1, v2); 
    for(i = 0; i<= vdist->size; i++){ 
     vdist->data[i] = (vdist->data[i])*(vdist->data[i]); 
     dist += vdist->data[i]; 
    } 
    dist = sqrt(dist); 
    return dist; 
    destroy_vector(vdist); 
} 

這是所有的代碼。

+0

我沒有看到任何內存泄漏。 valgrind說:「絕對丟失:0」,「可能丟失:0」 –

+0

@VaughnCato我試圖解決這個問題: '仍然可達:16個字節在2個塊' – Gera

+0

程序崩潰之前內存可以被釋放。 –

回答

3
case 8 : //suma 
     sscanf (mystring,"%s %s %s", charv1, str, charv2); 
     v1 = strtol((charv1+1) , NULL , 10); 
     v2 = strtol((charv2+1) , NULL , 10); 
     addorsub = add(v[v1-1], v[v2-1]); 
     printf("SUMA: %d %d\n", v1, v2); 
     print(addorsub); 
     break; 

這是你的問題。指針addorsub已經malloc'd,但add()函數返回malloc'd向量指針。所以add()函數內的vadd矢量指針覆蓋了addorsub指針,這使得分配的內存已經在addorsub指針中了......消失在空氣中。

sub()函數發生同樣的事情。在return語句之後實際上不可能銷燬分配的內存,因此在調用這些函數以保留內存之前,必須銷燬add()或sub()函數外的指針中的內存。因此在main()函數中,incr()函數,decr()函數等等。,您需要爲接收add()或sub()的指針的內容分配內存分配,並確保它是否位於循環的內部,以便在將指針重新分配給不同的目標之前銷燬當前分配的所有內存地址。

UPDATE:殺內存泄漏,現在我需要知道我可以初始化此聲明:

vector *addorsub = (vector*)malloc(sizeof(*addorsub)); 

你不會的。只要做到這一點

vector * addorsub = NULL; 

並確保addorsub在循環的每次迭代中獲得對free()的調用。

+0

哇,也就是說,它一定是這樣的。 但不知道如何才能返回vadd然後釋放它... 您可以舉一個例子或給出一些關於如何爲vadd/vsub刪除分配的內存的線索嗎? 非常感謝你非常非常muuuchhh – Gera

+0

我想我通過一個while while循環替換do ... while語句解決了這個問題。 我用新的valgrind警告更新了主帖,你知道我該如何解決'條件跳轉或移動取決於未初始化值(s)'? 謝謝。 – Gera

1

主要問題是程序在有機會釋放內存之前崩潰。這個問題的很大一部分似乎是在這裏:

line[strlen(line)] = ','; /* Replaces the end ] with a , */ 

應該

line[strlen(line)-1] = ','; /* Replaces the end ] with a , */ 

還有其他各種內存問題爲好。例如,addorsub已分配但未釋放。

一般來說,當使用valgrind時,嘗試從第一個錯誤開始並按照自己的方式工作。看到最後的結果會讓人產生誤解,因爲之前的錯誤可能會導致後面的錯誤產生副作用。

+0

非常感謝你,一直有助於進一步優化代碼,但我一直在valgrind中得到相同的錯誤。 我認爲錯誤可能來自do .. while語句 – Gera

+0

我是對的,問題來自於「do-while」,我將用valgrind的新信息更新帖子。 – Gera

+0

感謝您提供關於修復問題的自上而下的方法 –