I am trying to save information from a file to structs in the heap.
The problem is: if i print out the information in the for loop where i save the data, it works well, but when i print out the data outside that for loop i get only garbage
i wanna know why :( probably i am doing a bad work with the malloc
i could work inside the first for loop but i want to know what i am doing wrong
typedef struct{
int tipoDeCodificacion;
void* carta;
}pedido;
typedef struct{
void* nombre;
void* regalo;
}regalos;
void creacionRegalos(FILE *cartas){
FILE *final=fopen("regalos.txt","w");
int cantidadCartas, i;
fscanf(cartas,"%d\n",&cantidadCartas);
printf("%d\n",cantidadCartas);
pedido *Pedidos=(pedido *)malloc(sizeof(cantidadCartas));
regalos **Regalos=malloc(sizeof(regalos *)*cantidadCartas);
for(i=0;i<cantidadCartas;i++){
char *lineaCodificada=malloc(sizeof(char)*100);
int *tipo=malloc(sizeof(int));
fscanf(cartas,"%d\n",tipo);
Pedidos[i].tipoDeCodificacion=*tipo;
printf("%d\n",Pedidos[i].tipoDeCodificacion); //this print works well
fgets(lineaCodificada,100,cartas);
Pedidos[i].carta=lineaCodificada;
puts(Pedidos[i].carta); //this print works well
}
for (i = 0; i < cantidadCartas; i++) {
printf("%d\n",Pedidos[i].tipoDeCodificacion); //just prints garbage
printf("%s\n",(char *)Pedidos[i].carta);//prints garbage
}
}
The line:
pedido *Pedidos=(pedido *)malloc(sizeof(cantidadCartas));
is invalid. You are allocating memory for sizeof(int) bytes. You should:
pedido *Pedidos=(pedido *)malloc(sizeof(*Pedidos) * cantidadCartas);
allocate memory for contidadCartas count of pedido structures. The time you access Pedidos memory using pedido* pointer you do undefined behavior.
Your code is really hard to read, badly indented, with strange locale names, no error checking and it leaks memory for all malloc you call. A good code would check all error places if (Pedidos == NULL) { handle_error(); } and if(fscanf("%d", ....) != 1) etc. The allocation of int *typo = malloc(sizeof(int)); straight up leaks memory - it is nowhere freed. I also strongly encourage you to write all code, including all structure, variables and function names in english.
Related
This is a small piece of code that I made while trying to understand how malloc and pointers work.
#include <stdio.h>
#include <stdlib.h>
int *buffer (int count)
{
int *buffer = malloc (count * sizeof(int));
for (int i = 0; 0 <= i && i < count; i++)
{
buffer[i] = 0;
}
return &buffer;
}
int main ()
{
int size = 0;
int i = 0;
scanf ("%d", &size);
int *num = buffer (size);
while (i < size)
{
scanf ("%d", &num[i]);
i++;
}
}
For some reason that I can't understand, I keep getting a segmentation fault. This error repeatedly happens on the last scanf() and I do not know why. I know i have to pass pointer to scan f and num is already a pointer so i thought that i would not need to include the &. But, I received a segmentation fault earlier if i do not. Also, I believe I have allocated the correct amount of space using malloc but I am not sure. Any help with what is happening here would be appreciated.
You returned the pointer to the local variable buffer, which will banish on exiting the function buffer.
You should remove the & used in the return statement and return the pointer to allocated buffer.
Also checking whether malloc() is successful should be added.
There are a couple of issues that I can see, and one of them is definitely a problem.
In function, int *buffer (int count)
return &buffer;
This will return address of buffer which is already a local int * variable.
So when the return happens, variable buffer would no longer be valid. Hence, the address is invalid.
One of the ways to go ahead as of now would be avoiding a function call buffer and using calloc().
Because, subject to availability, calloc() will allocate the memory of requested length, which will be initialized to 0 by default.
Or, the other way would be making the buffer pointer a global variable.
Also, with existing implementation, there needs a piece of code which checks if malloc returned anything or not. That would indicate if the memory was allocated or not.
Something like this would do:
int *buffer = malloc (count * sizeof(int));
if(buffer == NULL)
{
// Some error handling
return 0;
}
Additionally, I see the for loop which looks a bit weird than what it should look like:
for (int i = 0; 0 <= i && i < count; i++)
I take that you are trying to loop the count times and fill a 0 in buffer. This could have been achieved by
for (int i = 0; i < count; i++)
So, a malloc() is followed by en error-check and then followed by a for to fill the allocated memory with zeroes. So, using calloc makes life a lot easier.
Importantly, you allocate memory but you don't seem to have a code that de-allocates (frees) it. There are ample of examples to refer for doing that. I would recommend you to read concepts like Memory Leakage, Dangling Pointers and using valgrind or similar thing to validate the memory usage.
As a side-note and not a rule of thumb, always make sure that the names you use for variables are different than the names you use with functions. That creates a hell a lot of confusion. Going ahead with existing naming habit, you'll have a tough day when the code is reviewed.
I'm having a little trouble doing a school project, and I can't post all my code here because it might be copied by my schoolmates.
I have created a Dynamic Struct called Messages with the variable inside it char ** phrases, int lines (number of phrases at the moment), int heaplines(max number of lines my char ** phrases can hold).
My program should work this way: it asks the user to insert messages, allocating memory to them and increasing the variable lines, which is the number of messages he has at the moment, if it reaches the max then I do an reallocation of +10 plus lines and it increases the heaplines. But my true problem is I cant allocate memory to the string the user has inserted because it gives me an error saying:
Incompatible Pointers types "char **" and "char *"
.
MSG->phrases=(char*)malloc((tamphrase+1)*sizeof(char));
Allocating the lines for the matrix of char ** msg it works perfectly, but when I try to allocate memory for the string that is going to be inserted it gives me that error on that line of code above.
Btw, how can I increment the lines of the matrix of phrases?
For example:
MSG->(phrases+i)=(char*)malloc((tamphrase+1)*sizeof(char));
(I know this is wrong, but I hope you guys know what I'm trying to say)
MSG->phrases=(char*)malloc((tamphrase+1)*sizeof(char)); is a char** so allocating memory to it would be
MSG->phrases=malloc((tamphrase+1)*sizeof(char*));
Well then for each of the tamphrase you allocate memory for holding characters.
MSG->phrases[i]=malloc((MAXLENOFLINE+1)*sizeof(char));
Also you should read about realloc to get an idea about the reallocating when you run out of already allocated memory in your code.
Don't cast the return value of malloc, it's unnecessary and doing so may suppress error in case error occurs.
If you understand the logic of pointers a bit then you wouldn't have problem writing these lines.
you said phrases are char**. Now think what a char** holds. It holds the address of char* variables. Now you will allocate a chunk of memory each capable of holding char* variables and then you return the starting address of it to phrases.
Now same way you think the other way, char* holds the address of a char variable. You will allocate a memory where you will store the char variables. You return the starting address to the char* variables.
phrases[i] holds that.
Without going into detail, the general structure of the code will be something like this
MSG->phrases=malloc((tamphrase+1)*sizeof(char*));
if( MSG->phrases == NULL ){
fprintf(stderr,"Error in malloc");
exit(1);
}
for(size_t i = 0; i < tamphrase+1; i++ ){
MSG->phrases[i]=malloc((MAX_LINE_LENGTH+1)*sizeof(char));
if( MSG->phrases[i] == NULL ){
fprintf(stderr,"Error in malloc");
exit(1);
}
}
...
...
// do cool stuff
..
..
//free the allocated memory
for(size_t i = 0; i < tamphrase+1; i++ ){
free(MSG->phrases[i]);
}
free(MSG->phrases);
we wrote a program that reads comma-separated integer-values into an array and tries processing them with a parallel structure.
By doing so, we found out that there is a fixed limitation for the maximum size of the dynamic array, which usually gets allocated dynamically by doubling the size. Yet for a dataset with more than 5000 values, we can't double it anymore.
I am a bit confused right now, since technically, we did everything the way other posts pointed out we should do (use realloc, don't use stack but heap instead).
Note that it works fine for any file with less or equal than 5000 values.
We also tried working with realloc, but to the same result.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// compile with gcc filename -lpthread -lm -Wall -Wextra -o test
int reader(int ** array, char * name) {
FILE *fp;
int data,row,col,count,inc;
int capacity=10;
char ch;
fp=fopen(name,"r");
row=col=count=0;
while(EOF!=(inc=fscanf(fp,"%d%c", &data, &ch)) && inc == 2){
if(capacity==count)
// this is the alternative with realloc we tried. Still the same issue.
//*array=malloc(sizeof(int)*(capacity*=2));
*array = realloc(*array, sizeof(int)*(capacity*=2));
(*array)[count++] = data;
//printf("%d ", data);
if(ch == '\n'){
break;
} else if(ch != ','){
fprintf(stderr, "format error of different separator(%c) of Row at %d \n", ch, row);
break;
}
}
// close file stream
fclose(fp);
//*array=malloc( sizeof(int)*count);
*array = realloc(*array, sizeof(int)*count);
return count;
}
int main(){
int cores = 8;
pthread_t p[cores];
int *array;
int i = 0;
array=malloc(sizeof(int)*10);
// read the file
int length = reader(&array, "data_2.txt");
// clean up and exit
free(array);
return 0;
}
EDIT: I included the realloc-command we tried and changed the values back to our original testing values (starting at 10). This didn't impact the result though, or rather still does not work. Thanks anyways for pointing out the errors! I also reduced the included code to the relevant part.
I can't really get my head around the fact that it should work this way, but doesn't, so it might just be a minor mistake we overlooked.
Thanks in advance.
New answer after question has been updated
The use of realloc is wrong. Always do realloc into a new pointer and check for NULL before overwriting the old pointer.
Like:
int* tmp = realloc(....);
if (!tmp)
{
// No more memory
// do error handling
....
}
*array = tmp;
Original answer (not fully valid after question has been updated)
You have some serious problems with the current code.
In main you have:
array=malloc(sizeof(int)*10); // This only allocates memory for 10 int
int length = reader(&array, "data_1.txt");
and in reader you have:
int capacity=5001;
So you assume that the array capacity is 5001 even though you only reserved memory for 10 to start with. So you end up writing outside the reserved array (i.e. undefined behavior).
A better approach could be to handle all allocation in the function (i.e. don't do any allocation in main). If you do that you shall initialize capacity to 0 and rewrite the way capacity grows.
Further, in reader you have:
if(capacity==count)
*array=malloc(sizeof(int)*(capacity*=2));
It is wrong to use malloc as you loose all data already in the array and leak memory as well. Use realloc instead.
Finally, you have:
*array=malloc( sizeof(int)*count);
Again this is wrong for the same reason as above. If you want to resize to the exact size (aka count) use realloc
Can't find what is wrong with this code, it works as expected when inputting exactly 4 values, but on the fifth call (before it even asks for scanf) it always gives me this error:
* glibc detected ./a2: double free or corruption (fasttop): 0x0916e018 **
Here's some code of my program:
typedef struct {
int i;
char str[25];
} typeX;
int main(){
int dSize = 0;
int *dSizePtr = &dSize;
dPointer = (typeX **)malloc(sizeof(typeX *)); // makes an array of pointers
int i;
for (i = 0; i < 100; i++)
makeElement(dPointer, dSizePtr); // Puts values into those pointers
free(dPointer);
return 0;
}
void makeElement(dPointer **, int *dSizePtr){
dPointer = (typeX **)realloc(dPointer, sizeof(typeX *)*(*dSizePtr+1)); // grow the array by one
if (typeX == NULL)
return; // some kind of quit statement, just return for now
dPointer[*dSizePtr] = (typeX *)malloc(sizeof(typeX)); // make a new pointer in the array
scanf("%s", dPointer[*dSizePtr]->str); // input the values of the struct (have to use scanf)
char input[20];
scanf("%s", input);
dPointer[*dSizePtr]->int = atoi(input);
++(*dSizePtr);
}
I know I don't have to make a dSizePtr and I can just pass in &dSize, but the way my program is currently set up (this isn't exactly the same, just compressed for readability), that's the way I have to pass it.
I honestly have no idea why this error is coming up. Been looking at my code for hours and reading online and haven't found a solution. Any help will be greatly appreciated!
The problem is that your function makeElement get the value of dPointer, not its reference. When you realloc the data, the originally allocated chunk is freed. But the dPointer outside of the makeElement scope is not changed;
The runtime error is delayed as the actual memory allocation is performed in quantities bigger than sizeof(typeX*)
This line is causing the double free.
dPointer = (typeX **)realloc(dPointer, sizeof(typeX *)*(*dSizePtr+1)); // grow the array by one
For the first few iterations of the loop in the caller the block of memory is large enough that realloc() doesn't have to do anything, and thus it returns the same pointer passed to it. But at some point the block of memory is too small and realloc() has to allocate a new block of memory and returns a pointer to it. That returned pointer is assigned to dPointer in makeElement() but it does not change the value of dPointer in the caller. So the caller continues to pass the old dPointer value into makeElement(), which passes it to realloc(), which notices that this pointer has been freed (by the call to realloc() that expanded the size of the array).
I have a question regarding this code. I write this code in my framework, and it caused the framework crashed. But when I rewrite this code below in a single file, but it works just fine. I was just wondering, is the code below is correct for memory allocation and freeing it? (especially for the part of msg->context_var.type = f;)
Thank you
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int value;
int price;
int old;
} type_t;
typedef struct {
type_t *type;
} context_t;
typedef struct {
context_t context_var;
} send_request;
void send_Message(send_request *msg)
{
type_t *f = 0;
f = malloc(sizeof(f));
msg->context_var.type = f;
msg->context_var.type->price = 1;
msg->context_var.type->value = 100;
msg->context_var.type->old =120;
printf("value of %d/n", msg->context_var.type->price);
free(f);
}
int main()
{
send_request *msg = 0;
msg = (send_request *) malloc(sizeof(send_request));
send_Message(msg);
free(msg);
return 0;
}
It's wrong.
f = malloc(sizeof(f)); /* Wrong */
f = malloc(sizeof(*f)); /* Better ? */
sizeof(f) will give you the size of a pointer on your machine; sizeof(*f) will give you the size of the object pointed to.
EDIT As requested by #Perception
When you allocate less than you need you're eliciting Undefined Behavior. Anything can happen (even the desired behavior) and it all depends on the platform, the environment (the moon phase, etc).
msg->context_var.type->value = 100; /* Writes beyond what's allocated. */
So, depending on the memory layout of the "framework" this might simply overwrite some memory and "work", or it could crash. Frankly I prefer when it crashes straight away.
You allocate an instance of context_t on the heap, and then msg->context_var.type gets the value of the resulting pointer f.
Since msg is a pointer parameter to the send_Message function, no reliable assumptions can be made about what is done with msg and its contents after your function exists. As such, when you go on to free the memory pointed to by f, you leave a dangling pointer in msg->context_var.type.
If the memory it points to is accessed after send_Message exists, there's a fair chance that you corrupt something vital (or read something crazy, like a pointer to 0xdeadbeef), as it might contain something completely different now.
Not only are you allocating wrong size (see cnicutar's answer)-- If you are attaching f to message that is passed by the framework, you probably don't want to free it before the function returns. You'll need to free it later, though-- probably through some other facility provided by the framework?