UPDATE: Memory leaks killed, now I need to know how can I initialize this statement:
vector *addorsub = (vector*)malloc(sizeof(*addorsub));
This is what I get from 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)
And this is the main program:
#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);
}
I checked all malloc and frees, but I think I'm leaving anything ...
any ideas? thank you very much.
EDIT:
Input example (int a .txt file as stdin):
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);
}
This is all the code.
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;
This is your problem. The pointer addorsub has already been malloc'd, but the add() function returns a vector pointer which is malloc'd. So the vadd vector pointer inside of the add() function is overwriting the addorsub pointer, which makes the allocated memory already in the addorsub pointer just...disappear into thin air.
The same thing happens with the sub() function. It's actually impossible to destroy the allocated memory after the return statement, so you have to destroy the memory in the pointer outside of the add() or sub() functions before you call those functions in order to preserve your memory.
So in the main() function, the incr() function, the decr() function, etc., you need to take out the memory allocation for anything that receives a pointer for add() or sub(), as well as making sure that if it's inside of a loop that you destroy any memory currently allocated before reassigning the pointer to a different address.
UPDATE: Memory leaks killed, now I need to know how can I initialize this statement:
vector *addorsub = (vector*)malloc(sizeof(*addorsub));
You won't. Just make it
vector * addorsub = NULL;
And make sure that addorsub gets a call to free() in every iteration of the loop.
The main issue is that the program is crashing before it has a chance to free the memory. A big part of the problem seems to be here:
line[strlen(line)] = ','; /* Replaces the end ] with a , */
it should be
line[strlen(line)-1] = ','; /* Replaces the end ] with a , */
There are various other memory issues as well. For example, addorsub is allocated but not freed.
In general, when using valgrind, try to start with the first error and work your way down. Looking at the end is misleading, since earlier errors can have the side-effect of causing the later ones.
Related
I am making a program for the school that must generate 1 million strings all different from each other and whose length varies from 3 to 20 characters, I immediately want to say that I have already finished the program and I have already generated the strings, but I wanted to, as a pastime, optimize it.
I initially conceived it by making a 2d array (array containing char arrays) and it worked but I wanted to make the string checking faster by saving each string in the column equal to its length, for example the string "Ci_3sa" which contains 6 characters is stored in arr[6][0][nOfChars] and instead a 4 characters long word in arr[4][0][nOfChars], I think I explained what I wanted to do .
I do not think I have made reference errors of the type of variables, because when I compile the code I do not get errors or warnings (I have active warnings), but when I execute the code it gives me an error in the dump core, I also tried to run the code in a debugger for C but however I don't understand what the problem is because it seems to work some times and in others it doesn't (but it never finished executing the program).
I would really like to understand what kind of mistake I made.
I assume the error is in the "checkStrings()" function
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#define N_STRINGS 1000000
#define MIN_CHARS 3
#define MAX_CHARS 20
#define ASCII_START 32 // 32 è lo spazio
#define ASCII_END 126
#define randnum(min, max) ((rand() % (int)(((max) + 1) - (min))) + (min))
char *generateRandomString(int size)
{
int i;
// char *charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-#'?!";
// printf("Dimensione del charset: %ld\n", strlen(charset));
char *res = malloc(size + 1);
for (i = 0; i < size; i++)
{
/*
int key = randnum(0, 69);
res[i] = charset[key];
*/
int key = (rand() % (ASCII_END - ASCII_START)) + ASCII_START;
res[i] = (char)key;
if (key == 92 || key == 32 || key == 34)
i--;
}
res[i] = '\0';
return res;
}
int checkStrings(char *strs[18][N_STRINGS], char *str, int size)
{
for (int i = 0; i < size; i++)
{
/*
printf("Lunghezza stringa\n: %ld", strlen(str));
printf("Vediamo : %s\n", str);
printf("Parola Array in posizione %d: %s\n", i, strs[i]);
printf("Parola Generata: %s\n", str);
*/
if (strcmp(strs[strlen(str) - 3][i], str) == 0)
return 1;
}
return 0;
}
void wirteOutput(char *outputFile, char *strs[18][N_STRINGS], int *ss, int isJson)
{
FILE *output;
if ((output = fopen(outputFile, "w+")) == NULL)
{
printf("errore nell'apertura del file output");
exit(2);
}
if (isJson == 1)
fprintf(output, "[\n"); // inizio array in json
for (int j = 0; j < 18; j++)
{
for (int i = 0; i < ss[j]; i++)
{
if (isJson == 1)
if (i < ss[j] - 1)
fprintf(output, "\"%s\",\n", strs[j][i]);
else
fprintf(output, "\"%s\"\n", strs[j][i]);
else
fprintf(output, "%s\n", strs[j][i]);
// printf("i: %d\n", i);
}
}
if (isJson == 1)
fprintf(output, "]\n"); // fine array in json
fclose(output);
}
int main()
{
// printf("Questo è il char 32: '%c'\n\n", 32);
srand(time(NULL));
// printf("%d\n", randnum(1, 70));
int percentage = 0;
int sizes[18] = {0};
char *strings[18][N_STRINGS];
printf("Starting to generate random strings\n\n");
for (int i = 0; i < N_STRINGS; i++)
{
int n = randnum(MIN_CHARS, MAX_CHARS);
// printf("Numero di lettere estratto: %d\n", n);
char *str = generateRandomString(n);
// printf("Parola generata: %s\n", str);
// sleep(1);
if (checkStrings(strings, str, sizes[strlen(str) - 3]) != 0)
{
// printf("find same word\n");
i--;
}
else
{
strings[strlen(str) - 3][i] = str;
sizes[strlen(str) - 3]++;
}
// if (i >= 10000 && N_STRINGS % i == 0 && ((100 * i) / N_STRINGS) % 10 == 0)
if (i >= (N_STRINGS / 100) && percentage != (100 * i) / N_STRINGS)
{
percentage = (100 * i) / N_STRINGS;
fputs("\033[A\033[2K", stdout);
rewind(stdout);
printf("%d%%\n", percentage); // 1000 : 100 = i : x
}
// printf("Parola assegnata: %s\n", strings[i]);
}
wirteOutput("output2.json", strings, sizes, 1);
wirteOutput("output2.txt", strings, sizes, 0);
printf("End\n");
return 0;
}
EDIT:
This is my test code and #AndreaWenzel i tried your solution but after some attempts it works, but I don't understand how this 3d array should work because according to the logic of this code it should only write the strings that have been generated and instead it writes me in the file 1 or 2 strings and in the other cases (null) even if the code reaches the end by writing "End".
This is the file
(null)
Ji+]
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
//#define N_STRINGS 1000000
#define N_STRINGS 100
#define MIN_CHARS 3
#define MAX_CHARS 20
#define ASCII_START 32 // 32 è lo spazio
#define ASCII_END 126
#define randnum(min, max) ((rand() % (int)(((max) + 1) - (min))) + (min))
char *generateRandomString(int size)
{
int i;
// char *charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-#'?!";
// printf("Dimensione del charset: %ld\n", strlen(charset));
char *res = malloc(size + 1);
for (i = 0; i < size; i++)
{
/*
int key = randnum(0, 69);
res[i] = charset[key];
*/
int key = (rand() % (ASCII_END - ASCII_START)) + ASCII_START;
res[i] = (char)key;
if (key == 92 || key == 32 || key == 34)
i--;
}
res[i] = '\0';
return res;
}
int checkStrings(char *strs[18][N_STRINGS], char *str, int size)
{
for (int i = 0; i < size; i++)
{
printf("Lunghezza stringa: %ld\n", strlen(str));
// sleep(1);
printf("Parola Array in posizione %d: %s\n", i, strs[strlen(str) - 3][i]);
printf("Parola Generata: %s\n", str);
if (strs[strlen(str) - 3][i] != NULL)
if (strcmp(strs[strlen(str) - 3][i], str) == 0)
return 1;
}
return 0;
}
void wirteOutput(char *outputFile, char *strs[18][N_STRINGS], int *ss, int isJson)
{
FILE *output;
if ((output = fopen(outputFile, "w+")) == NULL)
{
printf("errore nell'apertura del file output");
exit(2);
}
if (isJson == 1)
fprintf(output, "[\n"); // inizio array in json
for (int j = 0; j < 18; j++)
{
for (int i = 0; i < ss[j]; i++)
{
if (isJson == 1)
if (i < ss[j] - 1)
fprintf(output, "\"%s\",\n", strs[j][i]);
else
fprintf(output, "\"%s\"\n", strs[j][i]);
else
fprintf(output, "%s\n", strs[j][i]);
// printf("i: %d\n", i);
}
}
if (isJson == 1)
fprintf(output, "]\n"); // fine array in json
fclose(output);
}
int main()
{
// printf("Questo è il char 32: '%c'\n\n", 32);
srand(time(NULL));
// printf("%d\n", randnum(1, 70));
int percentage = 0;
int sizes[18] = {0};
// char *strings[18][N_STRINGS];
char *(*strings)[N_STRINGS];
strings = malloc(18 * sizeof *strings);
if (strings == NULL)
{
fprintf(stderr, "Memory allocation error!\n");
exit(EXIT_FAILURE);
}
printf("Starting to generate random strings\n\n");
for (int i = 0; i < N_STRINGS; i++)
{
int n = randnum(MIN_CHARS, MAX_CHARS);
// printf("Numero di lettere estratto: %d\n", n);
char *str = generateRandomString(n);
// printf("Parola generata: %s\n", str);
// sleep(1);
if (checkStrings(strings, str, sizes[strlen(str) - 3]) != 0)
{
// printf("find same word\n");
i--;
}
else
{
strings[strlen(str) - 3][i] = str;
sizes[strlen(str) - 3]++;
}
// if (i >= 10000 && N_STRINGS % i == 0 && ((100 * i) / N_STRINGS) % 10 == 0)
if (i >= (N_STRINGS / 100) && percentage != (100 * i) / N_STRINGS)
{
percentage = (100 * i) / N_STRINGS;
fputs("\033[A\033[2K", stdout);
rewind(stdout);
printf("%d%%\n", percentage); // 1000 : 100 = i : x
}
// printf("Parola assegnata: %s\n", strings[i]);
}
printf("Ecco quante parole sono state scritte\n");
for (int i = 0; i < 18; i++)
printf("%d\n", sizes[i]);
// wirteOutput("output2.json", strings, sizes, 1);
wirteOutput("output2.txt", strings, sizes, 0);
printf("End\n");
free(strings);
return 0;
}
I fixed the core dump problem, apparently, but the thing that turns my nose up in any case is that, in the test code, cmq when the words are generated and there are no similar ones, it does not assign them because so many times it has happened that was going to check for more than one null value within the same word length section.
This is another test after the changes:
(N_STRINGS = 50)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
1/E1-&E/3#K
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
(null)
#wLo!>p%QR|+bNUgs
(null)
(null)
(null)
(null)
(null)
(null)
(null)
x>KEeQ&tG[jgT9roWdt
(null)
(null)
(null)
(null)
The line
char *strings[18][N_STRINGS];
in the function main will allocate 18 * 1000000 * sizeof(char*) bytes on the stack, which is 144 MB on most platforms. This will likely cause a stack overflow. For example, on Linux, a typical maximum stack size is 8 MB.
You should generally not allocate more than a few kilobytes on the stack. I suggest that you allocate the memory on the heap instead, using malloc:
char *(*strings)[N_STRINGS];
strings = malloc( 18 * sizeof *strings );
if ( strings == NULL )
{
fprintf( stderr, "Memory allocation error!\n" );
exit( EXIT_FAILURE );
}
The pointer strings should behave like a decayed 2D/3D array (depending on how you see it). This is because I selected the type of the pointer in such a way that it points to a sub-array as a whole, instead of a single element of the sub-array.
Don't forget to call free when you no longer need the memory, otherwise you will have a memory leak.
Also, the line
strings[strlen(str) - 3][i] = str;
does not do what you want. This line should be the following:
strings[strlen(str)-3][sizes[strlen(str)-3]] = str;
After fixing these bugs, your program should look like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
//#define N_STRINGS 1000000
#define N_STRINGS 100
#define MIN_CHARS 3
#define MAX_CHARS 20
#define ASCII_START 32 // 32 è lo spazio
#define ASCII_END 126
#define randnum(min, max) ((rand() % (int)(((max) + 1) - (min))) + (min))
char *generateRandomString(int size)
{
int i;
// char *charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-#'?!";
// printf("Dimensione del charset: %ld\n", strlen(charset));
char *res = malloc(size + 1);
for (i = 0; i < size; i++)
{
/*
int key = randnum(0, 69);
res[i] = charset[key];
*/
int key = (rand() % (ASCII_END - ASCII_START)) + ASCII_START;
res[i] = (char)key;
if (key == 92 || key == 32 || key == 34)
i--;
}
res[i] = '\0';
return res;
}
int checkStrings(char *strs[18][N_STRINGS], char *str, int size)
{
for (int i = 0; i < size; i++)
{
printf("Lunghezza stringa: %ld\n", strlen(str));
// sleep(1);
printf("Parola Array in posizione %d: %s\n", i, strs[strlen(str) - 3][i]);
printf("Parola Generata: %s\n", str);
if (strs[strlen(str) - 3][i] != NULL)
if (strcmp(strs[strlen(str) - 3][i], str) == 0)
return 1;
}
return 0;
}
void wirteOutput(char *outputFile, char *strs[18][N_STRINGS], int *ss, int isJson)
{
FILE *output;
if ((output = fopen(outputFile, "w+")) == NULL)
{
printf("errore nell'apertura del file output");
exit(2);
}
if (isJson == 1)
fprintf(output, "[\n"); // inizio array in json
for (int j = 0; j < 18; j++)
{
for (int i = 0; i < ss[j]; i++)
{
if (isJson == 1)
if (i < ss[j] - 1)
fprintf(output, "\"%s\",\n", strs[j][i]);
else
fprintf(output, "\"%s\"\n", strs[j][i]);
else
fprintf(output, "%s\n", strs[j][i]);
// printf("i: %d\n", i);
}
}
if (isJson == 1)
fprintf(output, "]\n"); // fine array in json
fclose(output);
}
int main( void )
{
// printf("Questo è il char 32: '%c'\n\n", 32);
srand(time(NULL));
// printf("%d\n", randnum(1, 70));
int percentage = 0;
int sizes[18] = {0};
// char *strings[18][N_STRINGS];
char *(*strings)[N_STRINGS];
strings = malloc(18 * sizeof *strings);
if (strings == NULL)
{
fprintf(stderr, "Memory allocation error!\n");
exit(EXIT_FAILURE);
}
printf("Starting to generate random strings\n\n");
for (int i = 0; i < N_STRINGS; i++)
{
int n = randnum(MIN_CHARS, MAX_CHARS);
// printf("Numero di lettere estratto: %d\n", n);
char *str = generateRandomString(n);
// printf("Parola generata: %s\n", str);
// sleep(1);
if (checkStrings(strings, str, sizes[strlen(str) - 3]) != 0)
{
// printf("find same word\n");
i--;
}
else
{
strings[strlen(str)-3][sizes[strlen(str)-3]] = str;
sizes[strlen(str) - 3]++;
}
// if (i >= 10000 && N_STRINGS % i == 0 && ((100 * i) / N_STRINGS) % 10 == 0)
if (i >= (N_STRINGS / 100) && percentage != (100 * i) / N_STRINGS)
{
percentage = (100 * i) / N_STRINGS;
fputs("\033[A\033[2K", stdout);
rewind(stdout);
printf("%d%%\n", percentage); // 1000 : 100 = i : x
}
// printf("Parola assegnata: %s\n", strings[i]);
}
printf("Ecco quante parole sono state scritte\n");
for (int i = 0; i < 18; i++)
printf("%d\n", sizes[i]);
// wirteOutput("output2.json", strings, sizes, 1);
wirteOutput("output2.txt", strings, sizes, 0);
printf("End\n");
free(strings);
return 0;
}
This program writes the following to the file output2.txt:
ux*
&{;
)}I
XGo
LOh
V3)
8>q
GNX
#J7
^%|
-keU
m44T
_a;x
F*|+
w0nTc
21gMx
N>z/J
bWM|Y
#/=kr
ill&A
}MWQk
#6Ouab
ado8mR
mYtPO:
Ct?LJ,
QpC1=g
U+nF&*
oSQE+p
]N[TH(
'L_hwty
y{AGIR0
k>b5_Me4
(n2oQD$f
3>SKZ.?y
gb;gO,aq`
;mGV_joDp
pWF7A!3jK
$%ZD#l!4&
J?VFUI2gZ
X6{Z!Qs<5
`VMNvn[+B
+61rN2b0*S
w-4#8HV;!M
)dkU^(SD#:
#w;C%Xt-<N
Qz5+LLeN}u
Gzm1qCsy-=
Yyc3v}RW{=
B9-,q.A<ou
uv>m*`BQm5
Qsel*;+x'Y7
#0r;E7VMhKO
,G7pD^Z{OP%
ZiT2x:bI|d!
*koo)ltKdwO
%KI.9Zs}mDX
5Q}n77CU8$k
H#=KJQp=7v>
6*DvlN]NB6W
J^rM*$i:[9>(
7]jH#iP9|wg?
oS/-=,5->#^b
V8J#Y;Ks+qy6
jyt9c()ZNe1?
{&)tTLGH/%An
`eg}|ihyr_64
jS&>?p.X];y9=
{]KT&b1Au|(lk
]?d89=!^zZee^
Y&g[#,nX#]Rq#
'zh>xIXN?mMRf
Ycx2!-n#zVzDu
>cr#&g%:5#a%`
w-!#.ed4)[{Mk<
Vj{j-p#`8SqF#?+
5OHpfux>,1#9R6Z
EH*e`XWm%,&ak_5
*sm)N'IW{:?DbOd
;u-J;aDeR4J{GM=U
TE$i0Lv]V7%#T?pj
]Ed?tb#7!ham[:#m
Yi#m!Xr%Tfjzht+X
d7!#3SW#yt`&D,RsD
3R]/g$v5&`N{f}Ne)
#(UkF#8#9J*RvZ]1x
Afz(3;4S]PDJ3G|Sz
w##--N.^i1q>h3:y/Z
&<-o46#<Z?&Vsd6Obf
l#&^KCK?*(*!cb<3(u
PuuU(]M:V?Q[C'zO-2
'cT-0aK5u!0&vimv(DY
gr9`t*6?QSK{%B[#gXg
UEsgt5IDL1^62g8K6+}
BEYRZfo?gn4+pJi!j>P
PN#26}M{dT`Txv[N|y)!
46p#AnR<>TP&OMGv35BE
ANZZ>;4D?S!}V):j/Cl<
7bqAwAu6rhY&'}:&:=4;
O:9HKA))>^=g+]?kNh9Q
!cX'f6Dr#9Ok#?|NV-1R
Note that this program has memory leaks, because you are not freeing any of the strings allocated in the function generateRandomString.
Also, in the function main, the expression strlen(str)-3 is being used 4 times in total. Especially the call to the function strlen is rather expensive. Therefore, it would make sense to only call this function once and to save the result to a variable, so that you remember the result and don't have to call the function again.
I am implementing a kind of dynamic map which will grow slowly depending on the actions we would perform in it. Basically, it's about representing the path to take after a series of direction taken (up, down, right, left). Therefore, I am thinking of a double table to which I will eventually add rows and columns with realloc() method. By testing my displacement function for a given type of movement, I have a good result for the first time I call the function (and therefore no problem reallocating my memory). But on the second call, everything is bad and I still can not understand the cause of the non-functioning of the realloc.
It throws this error:
realloc(): invalid next size
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
char **tab;
int x;
int y;
int ligne;
int colonne;
} Path;
Path* InitPath(){
int i, j;
Path *myPath = (Path*) malloc(sizeof(Path));
myPath->ligne = 3;
myPath->colonne = 3;
myPath->tab = malloc(sizeof(char)* myPath->ligne );
for(i=0; i< myPath->ligne; i++)
myPath->tab[i] = malloc(sizeof(char)*myPath->colonne);
for(i=0; i<myPath->ligne; i++)
for(j=0; j<myPath->colonne; j++)
if( i ==1 && j ==1)
myPath->tab[i][j] = 'S';
else
myPath->tab[i][j] = '#';
myPath->x = 1;
myPath->y = 1;
return myPath;
}
void addWay(Path* myPath, char* theWay){
int i, j;
char copie;
if( strcmp("up",theWay)==0 ){
if( 0 == myPath->y -1 ){
//on ajoute une ligne
myPath->ligne+=1;
// printf("%ld\n", myPath->ligne * sizeof(char));
//on alloue de la memoire pour cette ligne
myPath->tab = realloc(myPath->tab, myPath->ligne * sizeof(char));
myPath->tab[myPath->ligne-1] = malloc(sizeof(char)*myPath->colonne);
//on la rempli
for(i = 0; i<myPath->colonne; i++){
if(i == 0 || i== myPath->colonne -1 )
myPath->tab[myPath->ligne-1][i] = '#';
else if (i==myPath->x)
myPath->tab[myPath->ligne -1][i] = '*';
else
myPath->tab[myPath->ligne -1][i] = ' ';
}
//on inverse
for(i=myPath->ligne -1; i > myPath->y; i-- ){
for(j=0; j<myPath->colonne; j++){
copie = myPath->tab[i][j];
myPath->tab[i][j] = myPath->tab[i-1][j];
myPath->tab[i-1][j] = copie;
}
}
} else {
myPath->y -= 1;
myPath->tab[myPath->x][myPath->y] = '*';
}
}
// else if(strcmp("down", theWay)){
// }else if(strcmp("left", theWay)){
// }else if(strcmp("right", theWay)){
// }
// return myPath;
}
void showPath(Path* myPath){
int i, j;
for(i=0; i< myPath->ligne; i++){
for(j=0; j< myPath->colonne; j++)
printf("%c", myPath->tab[i][j]);
printf("\n");
}
}
void destroyPath(Path* myPath){
free(myPath->tab);
free(myPath);
}
int main(){
Path* new = InitPath();
showPath(new);
addWay(new, "up"); //Well
printf("**********************\n");
addWay(new, "up"); // Error
showPath(new);
// printf("%d %d %d %d", new->x, new->y, new->ligne, new->colonne);
destroyPath(new);
}
i have to sort my arrays of record but when compare 2 record one of them has NULL value. At this moment my debug for C doesn't work so if someone could give me a link to show me "how to" use , cause make error when launch with "PreLaunch returned -1 exit status" and after theh "file doesn't exixt in the path"...but this was an offtopic,so..i leave my code below , maybe i'm wrong with the usage of pointers to function cause i tried to print every call of the function " compare" and show me numeber more time that i aspected.
Main:
#include "ordered_array.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define START_CAPACITY_RECORD 10
typedef struct {
int id;
char* field1;
int field2;
float field3;
}Record;
int compare_record_int(void* ele1, void* ele2){
if(ele1 == NULL){
fprintf(stderr,"precedes_record_int_field: the first parameter is a null pointer");
exit(EXIT_FAILURE);
}
if(ele2 == NULL){
fprintf(stderr,"precedes_record_int_field: the second parameter is a null pointer");
exit(EXIT_FAILURE);
}
Record *A = (Record*)ele1;printf("\n\nele1: %d",A->id);
Record *B = (Record*)ele2;printf("\nele2: %d\n",B->id);
if(A->id < B->id) return 1;
else if(A->id > B->id)return 2;
return 0;
}
int GetRecord(char* file_name,Record* A){
FILE *fd = fopen(file_name,"rt");int i=0;
char* st=(char*)malloc(100*sizeof(char*));
if(fd == NULL){
printf("GetRecord:path file doesn't exist");
exit(EXIT_FAILURE);
};
while(!feof(fd)){
fscanf(fd,"%s\n",st);
A[i].id=atoi(strtok(st, ";"));
A[i].field1 = strdup(strtok(NULL, ";"));
A[i].field2 = atoi(strtok(NULL, ";"));
A[i].field3 = atof(strtok(NULL, ";"));
i++;
}
fclose(fd);
return i;
}
void print_record(void* record){
Record *B = (Record*)record;
printf("\nValore %d field1 %s field2 %i field3 %f ",B->id,B->field1,B->field2,B->field3);
}
int main(int argc,char* argv[]){
OrderedArray* b = ordered_array_create();
Record* A = (Record*)malloc(START_CAPACITY_RECORD*sizeof(Record));
int dim = GetRecord("TEST.csv",A);
for(int i = 0; i<dim;i++){
ordered_array_add(b,&A[i]);
}
ordered_array_print(b,print_record);
ordered_array_sort_by(b,compare_record_int);
ordered_array_print(b,print_record);
ordered_array_free(b);
free(A);
}
Library(only the part with the sort methods,for others ask me to edit in the comment):
void ordered_array_sort_by(OrderedArray * a, int (*compare)(void*,void*)){
if(a== NULL){
fprintf(stderr,"ordered_array_sort_by: ordered_array parameter cannot be NULL");
exit(EXIT_FAILURE);
}
if(compare == NULL){
fprintf(stderr,"ordered_array_sort_by: function parameter cannot be NULL");
exit(EXIT_FAILURE);
}
a->compare = compare;
a->array = array_merge_binary_insertion(a);
}
void** array_merge_binary_insertion(OrderedArray *a){
if (ordered_array_size(a) == 1)return a->array;
int m = ordered_array_size(a) / 2;
OrderedArray *B = ordered_array_create(m);
for(int i=0;i<m;i++)ordered_array_add(B,a->array[i]);
OrderedArray *C = ordered_array_create(m);
for(int i=m;i<ordered_array_size(a);i++)ordered_array_add(C,a->array[i]);
if (m <= 10){
B->array = array_binary_insertion(B->array, ordered_array_size(B),a->compare);
C->array = array_binary_insertion(C->array, ordered_array_size(C),a->compare);
}else{
B->array = array_merge_binary_insertion(B);
C->array = array_merge_binary_insertion(C);
}
return array_merge(B->array, C->array,a->compare);
}
void** array_merge(void** B,void** C,int (*compare)(void*,void*)){
if (B == NULL) return C;
else if (C == NULL) return B;
int dimB = sizeof(B) + 1;
int dimC = sizeof(C) + 1;
OrderedArray *X = ordered_array_create(dimB+dimC);
int x = 0, y = 0, i = 0;
while ((i < dimB) || (x < dimC)){
if((B[i]==NULL)||(C[i]==NULL))printf("\nerrore");
if ((*compare)(B[i],C[x]) == 1){
X->array[y] = B[i];
i++;
} else{
X->array[y] = C[x];
x++;
}
y++;
}
return X->array;
}
void** array_binary_insertion(void** array,int size,int (*compare)(void*,void*)){
//ricontrollare la funzione, non sistema bene
if(size == 1)return array;
int j = 0, x, y, temp;
OrderedArray *temp_array = ordered_array_create(size);
temp_array->array[0] = array[0];
for (int i = 1; i < size; i++){
temp = (int)array[i];
x = array_binary_search(temp_array->array, temp, 0, j,compare);
y = j;
while (y >= x){
temp_array->array[y + 1] = temp_array->array[y];
y--;
}
temp_array->array[x] = (void*)temp;
j++;
}
return temp_array->array;
}
int array_binary_search(void** array,int a,int l,int h,int (*compare)(void*,void*)){
if((array[l]==NULL)||((void*)a==NULL))printf("\nerrore");
if (l >= h){
if ((*compare)((void*)a,array[l]) == 2)
return l + 1;
else
return l;
}
int m = (l + h) / 2;
if ((*compare)((void*)a,array[m]) == 0)
return m + 1;
else if ((*compare)((void*)a,array[m]) == 2)
return array_binary_search(array, a, m + 1, h,compare);
else
return array_binary_search(array, a, l, m - 1,compare);
}
Meanwhile if you have other advice would be gratefully accepted.
So this program crashes and tells me "Aborted (core dumped)" but only when my decleration of "GENERATIONS" is greater than 6... I know its a pain that I've uploaded the whole code but I really cant figure out where it is other than it's after the return from "fibonacci_quasicrystal_generator(GENERATIONS, crystal);", as the printf statement just after gets printed, then the message appears. Code below:
#define GENERATIONS 5
#define OUTFILE "frequencies.txt"
#define GNUPLOT_EXE "gnuplot"
#define GNUPLOT_SCRIPT "frequencyplot.script"
static void fibonacci_quasicrystal_generator(int generations, char * chain);
static int plot();
int main()
{
double k = 1.0, m_a = 100.0, m_b = 1.0, m = 0.0;
char * crystal = malloc(2);
//strcopy(crystal, "A"); //gsl_vector * y_vector = gsl_vector_calloc(CHAIN_LENGTH);
fibonacci_quasicrystal_generator(GENERATIONS, crystal);
if (crystal == NULL){
printf("Crystal write failed.");
exit(0);
}
int chain_length = strlen(crystal);
printf("%i member Crystal generated, after %i generations.\n", chain_length, GENERATIONS);
gsl_matrix * a_matrix = gsl_matrix_calloc(chain_length, chain_length);
gsl_matrix * b_matrix = gsl_matrix_calloc(chain_length, chain_length);
gsl_matrix_set_identity(b_matrix);
gsl_vector * eigenvalues_vector = gsl_vector_calloc(chain_length);
for (int i = 0; i < chain_length; ++i){
if (crystal[i] == 'A'){
m = m_a;
} else {
m = m_b;
}
for (int j = 0; j < chain_length; ++j){
if ((i == j) && (i != 0 && i != chain_length)){
gsl_matrix_set(a_matrix, i, j,(2*k)/m);
}
else if (i == j-1){
gsl_matrix_set(a_matrix, i, j,(-1)*(k/m));
}
else if (i == j+1){
gsl_matrix_set(a_matrix, i ,j, (-1)*(k/m));
}
}
}
gsl_eigen_gensymm_workspace * workspace = gsl_eigen_gensymm_alloc(chain_length);
gsl_eigen_gensymm(a_matrix, b_matrix, eigenvalues_vector, workspace);
gsl_eigen_gensymm_free(workspace);
free(crystal);
gsl_matrix_free(a_matrix);
gsl_matrix_free(b_matrix);
gsl_sort_vector(eigenvalues_vector);
FILE * outfile = fopen(OUTFILE, "w");
for (int i = 0; i < chain_length; ++i){
fprintf(outfile, "%e \t%i \r\n", pow(gsl_vector_get(eigenvalues_vector, i),2), i);
}
fclose(outfile);
gsl_vector_free(eigenvalues_vector);
plot();
return 0;
}
static void fibonacci_quasicrystal_generator(int generations, char * chain){
printf("generating fibonacci quasicrystal...\n");
int i;
i = 0;
char * chain_1 = malloc(2), * chain_2 = malloc(2), * tmp = malloc(2);
strcpy(chain_1, "B");
strcpy(chain_2, "A");
size_t chain_1_size = strlen(chain_1) + 1, chain_2_size = strlen(chain_2) + 1;
if (generations == 1){
chain = realloc(chain, chain_1_size);
snprintf(chain, chain_1_size, "%s", chain_1);
}
else if (generations == 2){
chain = realloc(chain, chain_2_size);
snprintf(chain, chain_2_size, "%s", chain_2);
}
else if (generations > 2){
size_t chain_3_size = strlen(chain_1) + strlen(chain_2) + 1;
char * chain_3 = malloc(chain_3_size);
printf("%i\n", generations);
for (i = 0; i < generations - 1; ++i){
printf("%i\n", i);
snprintf(chain_3, chain_3_size, "%s%s", chain_1, chain_2);
chain_1_size = chain_2_size;
chain_2_size = chain_3_size;
if ((tmp = realloc(chain_1, chain_1_size)) != NULL){
chain_1 = tmp;
}
if ((tmp = realloc(chain_2, chain_2_size)) != NULL){
chain_2 = tmp;
}
snprintf(chain_1, chain_1_size, "%s", chain_2);
snprintf(chain_2, chain_2_size, "%s", chain_3);
if (i < generations - 2){
chain_3_size = strlen(chain_1) + strlen(chain_2) + 1;
if ((tmp = realloc(chain_3, chain_3_size)) != NULL){
chain_3 = tmp;
} else {
printf("oops!\n");
exit(1);
}
}
}
chain = realloc(chain, chain_3_size);
snprintf(chain, chain_3_size, "%s", chain_3);
free(chain_3);
}
free(chain_1);
free(chain_2);
}
static int plot(){
char command[PATH_MAX];
snprintf(command, sizeof(command), "%s %s", GNUPLOT_EXE, GNUPLOT_SCRIPT);
system(command);
return 0;
}
The problem is that char *chain into fibonacci_quasicrystal_generator function has local scope: the function does not modify the crystal pointer of main, so that pointer is left with 2 bytes.
You can change the function to
static char *fibonacci_quasicrystal_generator(int generations, char * chain)
{
// YOUR STUFF
return chain;
}
And call it from main using
crystal = fibonacci_quasicrystal_generator(GENERATIONS, crystal);
You can achieve the same using a double pointer so
static void ibonacci_quasicrystal_generator(int generations, char ** chain)
I'm trying to implement a program that operates on a list of generic value nodes (pointers to void). The program works as follows: Read each line of an input file that translates each line, interprets and performs a function.
Performs functions such as addition, subtraction, normalization, distance, increment, decrement ... Running with the values of the nodes that are almost floats vectors.
To compile use:
g+ +-g-Wall-Wextra-Werror-pedantic main.cpp-o metbasicos.cpp metintermedios.cpp metavanzados.cpp eda.exe and I have no problems.
By using Valgrind've managed to eliminate all potential memory leaks and errors but one that I like and I can not resist putting it.
(valgrind - tool = memcheck - leak-check = full - show-reachable = yes. / eda.exe)
that's the whole main.cpp
int main(){
Lista *L = create_list();
char *mystring = NULL;
char *str, *charv1, *charv2, *simbol;
char *vec = NULL;
int operation, Lsize, v1, v2, res; /
vector *auxv1 = NULL;
vector *auxv2 = NULL;
Nodo *ultimo = NULL;
str = charv1 = charv2 = simbol = NULL;
while (fgets (mystring ,100 , stdin) != NULL){ // line 21, where the errors happens
sscanf (mystring,"%s",str);
res = strlen (str); /
if(mystring[0] == 'p') operation = 1; // print
else if(mystring[0] == 'i') operation = 2; // increase
else if(mystring[0] == 'd') {
if(mystring[1] == 'i') operation = 4; // distance
else if(mystring[1] == 'e') operation = 5; // decrease
else operation = 10; // destroy
}
else if(mystring[0] == 'n') {
if (mystring[1] == 'e') operation = 13; //nearest
else{
if (res == 4) operation = 7; // norm
else operation = 6; // normalize
}
}
else if(mystring[0] == 'c'){
if (mystring[1] == 'r') operation = 11; // create
else operation = 12; // clone
}
else{
sscanf (mystring,"%s %s",str, simbol);
if (simbol[0] == '+') operation = 8; // +
else if(simbol[0] == '-') operation = 9; // -
else operation = 3; // dot
}
switch(operation)
{
case 1 : // print
sscanf (mystring,"%s %s",str, charv1);
v1 = strtol((charv1+1) , NULL , 10);
if (v1 > Lsize) printf ("ERROR");
else {
for (int i = v1; v1>Lsize-i; i++) next(L);
auxv1 = (vector*)(current(L))->valor;
print(auxv1);
L->actual = ultimo;
}
break;
case 2 : // increase
sscanf (mystring,"%s %s %s",str, charv1, charv2);
v1 = strtol((charv1+1) , NULL , 10);
v2 = strtol((charv2+1) , NULL , 10);
if (v1 > Lsize || v2 > Lsize) printf ("ERROR");
else {
for (int i = v1; v1>Lsize-i; i++) next(L);
auxv1 = (vector*)(current(L))->valor;
L->actual = ultimo;
for (int i = v2; v2>Lsize-i; i++) next(L);
auxv2 = (vector*)(current(L))->valor;
L->actual = ultimo;
incr(auxv1, auxv2);
for (int i = v1; v1>Lsize-i; i++) next(L);
L->actual->valor = (void*)auxv1;
ultimo = L->actual;
}
break;
case 3 : // dot
sscanf (mystring,"%s %s %s",charv1, str, charv2);
v1 = strtol((charv1+1) , NULL , 10);
v2 = strtol((charv2+1) , NULL , 10);
if (v1 > Lsize || v2 > Lsize) printf ("ERROR");
else {
for (int i = v1; v1>Lsize-i; i++) next(L);
auxv1 = (vector*)(current(L))->valor;
L->actual = ultimo;
for (int i = v2; v2>Lsize-i; i++) next(L);
auxv2 = (vector*)(current(L))->valor;
L->actual = ultimo;
printf("%f\n", dot(auxv1, auxv2));
}
break;
case 4 : // distance
sscanf (mystring,"%s %s %s", str, charv1, charv2);
v1 = strtol((charv1+1) , NULL , 10);
v2 = strtol((charv2+1) , NULL , 10);
if (v1 > Lsize || v2 > Lsize) printf ("ERROR");
else {
for (int i = v1; v1>Lsize-i; i++) next(L);
auxv1 = (vector*)(current(L))->valor;
L->actual = ultimo;
for (int i = v2; v2>Lsize-i; i++) next(L);
auxv2 = (vector*)(current(L))->valor;
L->actual = ultimo;
printf("%f\n", distance(auxv1, auxv2));
}
break;
case 5 : // decrease
sscanf (mystring,"%s %s %s",str, charv1, charv2);
v1 = strtol((charv1+1) , NULL , 10);
v2 = strtol((charv2+1) , NULL , 10);
if (v1 > Lsize || v2 > Lsize) printf ("ERROR");
else {
for (int i = v1; v1>Lsize-i; i++) next(L);
auxv1 = (vector*)(current(L))->valor;
L->actual = ultimo;
for (int i = v2; v2>Lsize-i; i++) next(L);
auxv2 = (vector*)(current(L))->valor;
L->actual = ultimo;
decr(auxv1, auxv2);
for (int i = v1; v1>Lsize-i; i++) next(L);
L->actual->valor = (void*)auxv1;
ultimo = L->actual;
}
break;
case 6 : // normalize
sscanf (mystring,"%s %s",str, charv1);
v1 = strtol((charv1+1) , NULL , 10);
if (v1 > Lsize) printf ("ERROR");
else {
for (int i = v1; v1>Lsize-i; i++) next(L);
auxv1 = (vector*)(current(L))->valor;
normalize(auxv1);
L->actual->valor = (void*)auxv1;
ultimo = L->actual;
}
break;
case 7 : // norm
sscanf (mystring,"%s %s",str, charv1);
v1 = strtol((charv1+1) , NULL , 10);
if (v1 > Lsize) printf ("ERROR");
else {
for (int i = v1; v1>Lsize-i; i++) next(L);
auxv1 = (vector*)(current(L))->valor;
printf("%.3f\n", norm(auxv1));
L->actual = ultimo;
}
break;
case 8 : // +
sscanf (mystring,"%s %s %s", charv1, str, charv2);
v1 = strtol((charv1+1) , NULL , 10);
v2 = strtol((charv2+1) , NULL , 10);
if (v1 > Lsize || v2 > Lsize) printf ("ERROR");
else {
for (int i = v1; v1>Lsize-i; i++) next(L);
auxv1 = (vector*)(current(L))->valor;
L->actual = ultimo;
for (int i = v2; v2>Lsize-i; i++) next(L);
auxv2 = (vector*)(current(L))->valor;
L->actual = ultimo;
insert(L,crear_nodo_floatvec(add(auxv1, auxv2)));
ultimo = L->actual;
print((vector*)(current(L))->valor);
Lsize++;
}
break;
case 9 : // -
sscanf (mystring,"%s %s %s", charv1, str, charv2);
v1 = strtol((charv1+1) , NULL , 10);
v2 = strtol((charv2+1) , NULL , 10);
if (v1 > Lsize || v2 > Lsize) printf ("ERROR");
else {
for (int i = v1; v1>Lsize-i; i++) next(L);
auxv1 = (vector*)(current(L))->valor;
L->actual = ultimo;
for (int i = v2; v2>Lsize-i; i++) next(L);
auxv2 = (vector*)(current(L))->valor;
L->actual = ultimo;
insert(L,crear_nodo_floatvec(sub(auxv1, auxv2)));
ultimo = L->actual;
print((vector*)(current(L))->valor);
Lsize++;
}
break;
case 10 : // destroy
sscanf (mystring, "%s %s", str, charv1);
v1 = strtol((charv1+1) , NULL , 10);
if (v1 > Lsize) printf ("ERROR");
else {
for (int i = v1; v1>Lsize-i; i++) next(L);
if (v1 == Lsize) {
ultimo = L->actual->siguiente; //si eliminamos el último, asignamos el último al anterior //ojo
remove(L);
Lsize--;
}
else {
remove(L);
Lsize--;
L->actual = ultimo; //ojo
}
}
break;
case 11 : // create
vec = (char *)malloc(sizeof(char)*93); //100 - tamaño de str
sscanf (mystring, "%s %s", str, vec);
printf("%s %s \n", str, vec);
insert(L, crear_nodo_floatvec(create_vector(NumsVector(vec,strlen(vec)), getfloat(vec)))); //Creamos un nodo cuyo valor sea un vector de floats y lo insertamos en la lista
ultimo = L->actual; //ojo
Lsize++;
break;
case 12 : // clone
sscanf (mystring, "%s %s", str, charv1);
v1 = strtol((charv1+1) , NULL , 10);
if (v1 > Lsize) printf ("ERROR");
else {
for (int i = v1; v1>Lsize-i; i++) next(L);
auxv1 = (vector*)(current(L))->valor;
insert(L,crear_nodo_floatvec(create_vector(auxv1->size, auxv1->data))); //Creamos una copia del nodo indicado y lo insertamos
ultimo = L->actual; //ojo
Lsize++;
}
break;
case 13 : // nearest := vector* nearest(Lista* l, vector* v); *
sscanf (mystring,"%s %s",str, charv1);
v1 = strtol((charv1+1) , NULL , 10);
if (v1 > Lsize) printf ("ERROR");
else {
for (int i = v1; v1>Lsize-i; i++) next(L);
auxv1 = (vector*)(current(L))->valor;
print(nearest(L,auxv1));
L->actual = ultimo;
}
break;
default :
printf("operation value is: %d\n", operation);
break;
operation = 0;
}
}
Here you have the file that contains the implementation of some basic functions and implementation of the node vector and list:
typedef struct {
float* data;
int size;
}vector;
struct Nodo{
void* valor;
struct Nodo* siguiente;
};
struct Lista{
Nodo* primero;
Nodo* actual;
};
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;
destroy_vector(newvect);
}
void destroy_vector(vector* v){
free(v->data);
free(v);
}
void print(vector* v){
int size = v->size, i;
if (v == NULL) printf("ERROR");
else{
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]);
}
}
Lista* create_list() //Creamos espacio en la lista
{
Lista *L = NULL;
return L;
}
void insert(Lista* l, Nodo* nodo){
Nodo *Naux = (Nodo*)malloc(sizeof(nodo));
Naux->valor = l->actual->valor;
Naux->siguiente = l->actual->siguiente;
l->actual = nodo;
nodo->siguiente = Naux;
free(Naux->siguiente);
free(Naux->valor);
free(Naux);
}
bool end(Lista* l){
return l->actual == NULL;
}
bool is_empty(Lista* l) {
return l->actual->valor == NULL;
}
void next(Lista* l){
if(end(l)) printf ("Error, final de lista");
else l->actual = l->actual->siguiente;
}
void remove(Lista* l){
if(not end(l)) {
Nodo *Naux = (Nodo*)malloc(sizeof(Nodo));
Naux = l->actual->siguiente;
l->actual->valor = Naux->valor;
l->actual->siguiente = Naux->siguiente;
free(Naux->siguiente);
free(Naux->valor);
free(Naux);
}
}
int size(Lista* l){
if(not is_empty(l)) return sizeof(l->actual->valor);
else return 0;
}
Nodo* current(Lista* l){
return l->actual;
}
Nodo* crear_nodo(){
Nodo *Naux = NULL;
return Naux;
}
Nodo* crear_nodo_floatvec(vector* valor) {
Nodo *Naux = crear_nodo();
Naux->valor = (vector*)malloc(sizeof(valor));
Naux->valor = (void*)valor;
return Naux;
}
int NumsVector(char *linea, int size){
int numsvector = 1;
int n;
for(n = 2; n<= size; n++){
if (linea[n] != '[' && linea[n] != ']'){
if(linea[n] == 44){
numsvector = numsvector + 1;
}
}
}
return numsvector;
}
float* getfloat(char *vec){
int size = strlen(vec);
vec[size] = '\0';
int n = NumsVector(vec,size), j = 0;
float *vf = (float*)malloc(n*sizeof(float));
vec[size-1]= ',';
char *p = vec + 1;
do {
sscanf(p, "%f,", &vf[j]);
while (*(p++) != ',') ;
}
while (++j < n);
return vf;
}
When I launch Valgrind, it shows me the next errors:
Memcheck, a memory error detector
==9392== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==9392== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==9392== Command: ./eda.exe
==9392==
==9392== Invalid write of size 1
==9392== at 0x519E244: _IO_getline_info (iogetline.c:84)
==9392== by 0x519D06A: fgets (iofgets.c:58)
==9392== by 0x401AA3: main (main.cpp:21)
==9392== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==9392==
==9392==
==9392== Process terminating with default action of signal 11 (SIGSEGV)
==9392== Access not within mapped region at address 0x0
==9392== at 0x519E244: _IO_getline_info (iogetline.c:84)
==9392== by 0x519D06A: fgets (iofgets.c:58)
==9392== by 0x401AA3: main (**main.cpp:21**)
==9392== If you believe this happened as a result of a stack
==9392== overflow in your program's main thread (unlikely but
==9392== possible), you can try to increase the size of the
==9392== main thread stack using the --main-stacksize= flag.
==9392== The main thread stack size used in this run was 8388608.
==9392==
==9392== HEAP SUMMARY:
==9392== in use at exit: 0 bytes in 0 blocks
==9392== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==9392==
==9392== All heap blocks were freed -- no leaks are possible
==9392==
==9392== For counts of detected and suppressed errors, rerun with: -v
==9392== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
When I try to execute the program it also shows me Segmentation fault, Core dumped
Is there anyone that can help me please?
the greatest part of the variables are written in spanish, I guess that's no a problem to understand de code.
Thank you
Look at theese two lines:
char *mystring = NULL;
and
while (fgets (mystring ,100 , stdin) != NULL){
You're dereferencing a NULLpointer.
You sure you don't want e.g.
char mystring[100];