3

更新:内存泄漏被杀死,现在我需要知道如何初始化这个语句:

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

这是我从 valgrind 得到的:

gerasg@gerasg-iMac:~/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 和 frees,但我想我要留下任何东西......

有任何想法吗?非常感谢您。

编辑:

输入示例(将 .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

结构:

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

metabasicos.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);
}

这是所有的代码。

4

2 回答 2

6
    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 处理,但是 add() 函数返回了一个进行了 malloc 处理的向量指针。所以 add() 函数内部的 vadd 向量指针正在覆盖 addorsub 指针,这使得已经在 addorsub 指针中分配的内存......消失得无影无踪。

sub() 函数也会发生同样的事情。实际上不可能在 return 语句之后销毁分配的内存,因此您必须在调用 add() 或 sub() 函数之前销毁指针中的内存,然后再调用这些函数以保留内存。

所以在 main() 函数、incr() 函数、decr() 函数等中,你需要为任何接收到 add() 或 sub() 指针的东西取出内存分配,以及使确保如果它在循环内部,则在将指针重新分配给不同地址之前销毁当前分配的任何内存。

更新:内存泄漏被杀死,现在我需要知道如何初始化这个语句:

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

你不会的。做吧

    vector * addorsub = NULL;

并确保 addorsub 在循环的每次迭代中都调用 free() 。

于 2013-10-20T21:40:11.770 回答
3

主要问题是程序在有机会释放内存之前就崩溃了。问题的很大一部分似乎在这里:

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

它应该是

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

还有其他各种内存问题。例如,addorsub已分配但未释放。

通常,在使用 valgrind 时,请尝试从第一个错误开始,然后逐步进行。查看结尾会产生误导,因为早期的错误可能会产生导致后面错误的副作用。

于 2013-10-20T21:13:35.337 回答