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);
Related
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.
I'm attempting to read sequences from a FASTA file into a table of structs that I've created, which each contain a character array member called "seq". My code seems to work well for the first loop, but when I realloc() memory for the second sequence, the pointer seems to point to garbage values and then the strcat() method gives me a segfault.
Here's the whole FASTA file I'm trying to read from:
>1
AAAAAAAAAAGWTSGTAAAAAAAAAAA
>2
LLLLLLLLLLGWTSGTLLLLLLLLLLL
>3
CCCCCCCCCCGWTSGTCCCCCCCCCCC
Here's the code (sorry that some of the variable names are in french):
typedef struct _tgSeq { char *titre ; char *seq ; int lg ; } tgSeq ;
#define MAX_SEQ_LN 1000
tgSeq* readFasta(char *nomFile) {
char ligne[MAX_SEQ_LN];
tgSeq *lesSeq = NULL;
int nbSeq=-1;
FILE *pF = fopen(nomFile, "r");
while(fgets(ligne, MAX_SEQ_LN, pF) != NULL) {
if(ligne[0] == '>') {
/*create a new sequence*/
nbSeq++;
//reallocate memory to keep the new sequence in the *lesSeq table
lesSeq = realloc(lesSeq, (nbSeq)*sizeof(tgSeq));
//allocate memory for the title of the new sequence
lesSeq[nbSeq].titre = malloc((strlen(ligne)+1)*sizeof(char));
//lesSeq[nbSeq+1].titre becomes a pointer that points to the same memory as ligne
strcpy(lesSeq[nbSeq].titre, ligne);
//Now we create the new members of the sequence that we can fill with the correct information later
lesSeq[nbSeq].lg = 0;
lesSeq[nbSeq].seq = NULL;
} else {
/*fill the members of the sequence*/
//reallocate memory for the new sequence
lesSeq[nbSeq].seq = realloc(lesSeq[nbSeq].seq, (sizeof(char)*(lesSeq[nbSeq].lg+1+strlen(ligne))));
strcat(lesSeq[nbSeq].seq, ligne);
lesSeq[nbSeq].lg += strlen(ligne);
}
}
// Close the file
fclose(pF);
return lesSeq;
}
For the first line (AAAAAAAAAAGWTSGTAAAAAAAAAAA), lesSeq[nbSeq].seq = realloc(lesSeq[nbSeq].seq, (sizeof(char)*(lesSeq[nbSeq].lg+1+strlen(ligne)))); gives me an empty character array that I can concatenate onto, but for the second line (LLLLLLLLLLGWTSGTLLLLLLLLLLL) the same code gives me garbage characters like "(???". I'm assuming the problem is that the reallocation is pointing towards some sort of garbage memory, but I don't understand why it would be different for the first line versus the second line.
Any help you could provide would be greatly appreciated! Thank you!
The problem here is the first realloc gets the value of nbSeq as 0 which does not allocate any memory.
Replace
int nbSeq=-1;
with
int nbSeq=0;
Access the index with lesSeq[nbSeq - 1]
Some programmer dude already pointed out that you do not allocate enough memory.
You also seem to expect some behaviour from realloc that will not happen.
You call realloc with NULL pointers. This will make it behave same as malloc.
For the first line (AAAAAAAAAAGWTSGTAAAAAAAAAAA), ...= realloc(); gives me an empty character array that I can concatenate onto, but for the second line (LLLLLLLLLLGWTSGTLLLLLLLLLLL) the same code gives me garbage characters like "(???".
You should not expect any specifiy content of your allocated memory. Especially the memory location is not set to 0. If you want to rely on that, you can use calloc.
Or you simply assign a 0 to the first memory location.
You do not really concatenaty anything. Instead you allocate new memory where you could simply use strcpy instead of strcat.
In the following function, I am parsing string form a linked list and giving values to struct array. Is there any way that let me not use mallocs inside while loop.I can not handle glibc errors, so looking for other way.I tried to use char arrays instead of char* for the struct fields. But I am getting seg error. Actually the function is working, but I ahve to call the function 15000 times later, so I want to make sure it won't cause any memory trouble that time.
struct CoordNode
{
int resNum;
double coordX;
double coordY;
double coordZ;
char atomName[4];
};
void parseCrdList()
{
int resNum=1;
int tAtomNum,i;
char *tcoordX, *tcoordY, *tcoordZ, *tatomName, tresNum[5];
ccur_node=headCoord_node->next;
struct CoordNode *t;
t=malloc(numofRes*sizeof(struct CoordNode));
i=0;
while (ccur_node!=NULL)
{
tresNum=malloc(5*sizeof(char));
memcpy(tresNum,ccur_node->crdRow+26,4);
resNum=atoi(tresNum);
t[i].resNum=resNum;
tcoordX=malloc(8*sizeof(char));
memcpy(tcoordX,ccur_node->crdRow+35,7);
tcoordY=malloc(8*sizeof(char));
memcpy(tcoordY,ccur_node->crdRow+43,7);
tcoordZ=malloc(8*sizeof(char));
memcpy(tcoordZ,ccur_node->crdRow+51,7);
t[i].coordX=strtod(tcoordX,NULL);
t[i].coordY=strtod(tcoordY,NULL);
t[i].coordZ=strtod(tcoordZ,NULL);
tatomName=malloc(4*sizeof(char));
memcpy(tatomName,ccur_node->crdRow+17,3);
strcpy(t[i].atomName,tatomName);
old_ccur_node=ccur_node;
ccur_node=ccur_node->next;
//free(old_ccur_node);
i++;
}
numofRes=i;
addCoordData(t);
//free(t);
t=NULL;
}
A couple of thoughts and guesses.
First, as I mentioned before, sizeof(char) is always 1 byte in C, it's actually standard byte definition in C. So remove those as completely unnecessary and hard to read.
Back to the main problem.
You never use array of chars bigger than 8, so just make it statically 8 bytes long. If you have to call you function 15k times, that will save you tons of time(malloc takes time to allocate memory for you).
Given information from the question I guess your segfault was the cause of not initialising memory you allocated with malloc or reserved for auto char [8] with its declaration
1. You allocate (or 2nd version - declare 8-byte array) 8 bytes. It works fine. But you get 8 bytes full of trash here.
2. You copy 7 bytes from your list. And that's fine, too. But you forget to NULL terminate, so if you try to print it out back, you get segfault.EDIT If it works then probably you got lucky, because it shouldn't.
Solution
Replace char * witch char [8], remove all mallocs and frees corresponding to those char *, null terminate all your char[8] after strcpy, strncpy, or memcpy (whatever your choice is, depending on how confident you are that your data in list is correct) data to them.
Check your code with valgrind before further use, too.
It's surprising you saying this function worked for you. From what I see from your code I had a lot of memory leaks to begin with because non of those 8-byte mallocs was ever fried.
The second thing is that it looks like you're allocating array of CoordNode before knowing the actual number of data records to parse. I added proper numofRes calculation before allocation.
Since you don't modify input data you don't actually need all those mallocs and memcpy's, you can use crdRow in strtod() immediatly, assuming it has char * type.
The last thing: it's generally a bad practice to do allocation in one place and freeing data in another. So it's better you free your headCoord_node structure in a place where it was allocated, after parsing it. The decision of freeing t depends on how addCoordData(t) treats its parameter.
void parseCrdList()
{
struct CoordNode *t;
int i;
// count number of records to parse
numofRes = 0;
ccur_node = headCoord_node->next;
while (ccur_node != NULL)
{
numofRes++;
ccur_node=ccur_node->next;
}
t=malloc(numofRes*sizeof(struct CoordNode));
i=0;
ccur_node = headCoord_node->next;
while (ccur_node!=NULL)
{
t[i].resNum=atoi(ccur_node->crdRow+26);
t[i].coordX=strtod(ccur_node->crdRow+35,NULL);
t[i].coordY=strtod(ccur_node->crdRow+43,NULL);
t[i].coordZ=strtod(ccur_node->crdRow+51,NULL);
strncpy(t[i].atomName,ccur_node->crdRow+17,4);
ccur_node=ccur_node->next;
i++;
}
numofRes=i;
addCoordData(t);
//free(t); // <<< it depends on how addCoordData treats t
}
I have an array, say, text, that contains strings read in by another function. The length of the strings is unknown and the amount of them is unknown as well. How should I try to allocate memory to an array of strings (and not to the strings themselves, which already exist as separate arrays)?
What I have set up right now seems to read the strings just fine, and seems to do the post-processing I want done correctly (I tried this with a static array). However, when I try to printf the elements of text, I get a segmentation fault. To be more precise, I get a segmentation fault when I try to print out specific elements of text, such as text[3] or text[5]. I assume this means that I'm allocating memory to text incorrectly and all the strings read are not saved to text correctly?
So far I've tried different approaches, such as allocating a set amount of some size_t=k , k*sizeof(char) at first, and then reallocating more memory (with realloc k*sizeof(char)) if cnt == (k-2), where cnt is the index of **text.
I tried to search for this, but the only similar problem I found was with a set amount of strings of unknown length.
I'd like to figure out as much as I can on my own, and didn't post the actual code because of that. However, if none of this makes any sense, I'll post it.
EDIT: Here's the code
int main(void){
char **text;
size_t k=100;
size_t cnt=1;
int ch;
size_t lng;
text=malloc(k*sizeof(char));
printf("Input:\n");
while(1) {
ch = getchar();
if (ch == EOF) {
text[cnt++]='\0';
break;
}
if (cnt == k - 2) {
k *= 2;
text = realloc(text, (k * sizeof(char))); /* I guess at least this is incorrect?*/
}
text[cnt]=readInput(ch); /* read(ch) just reads the line*/
lng=strlen(text[cnt]);
printf("%d,%d\n",lng,cnt);
cnt++;
}
text=realloc(text,cnt*sizeof(char));
print(text); /*prints all the lines*/
return 0;
}
The short answer is you can't directly allocate the memory unless you know how much to allocate.
However, there are various ways of determining how much you need to allocate.
There are two aspects to this. One is knowing how many strings you need to handle. There must be some defined way of knowing; either you're given a count, or there some specific pointer value (usually NULL) that tells you when you've reached the end.
To allocate the array of pointers to pointers, it is probably simplest to count the number of necessary pointers, and then allocate the space. Assuming a null terminated list:
size_t i;
for (i = 0; list[i] != NULL; i++)
;
char **space = malloc(i * sizeof(*space));
...error check allocation...
For each string, you can use strdup(); you assume that the strings are well-formed and hence null terminated. Or you can write your own analogue of strdup().
for (i = 0; list[i] != NULL; i++)
{
space[i] = strdup(list[i]);
...error check allocation...
}
An alternative approach scans the list of pointers once, but uses malloc() and realloc() multiple times. This is probably slower overall.
If you can't reliably tell when the list of strings ends or when the strings themselves end, you are hosed. Completely and utterly hosed.
C don't have strings. It just has pointers to (conventionally null-terminated) sequence of characters, and call them strings.
So just allocate first an array of pointers:
size_t nbelem= 10; /// number of elements
char **arr = calloc(nbelem, sizeof(char*));
You really want calloc because you really want that array to be cleared, so each pointer there is NULL. Of course, you test that calloc succeeded:
if (!arr) perror("calloc failed"), exit(EXIT_FAILURE);
At last, you fill some of the elements of the array:
arr[0] = "hello";
arr[1] = strdup("world");
(Don't forget to free the result of strdup and the result of calloc).
You could grow your array with realloc (but I don't advise doing that, because when realloc fails you could have lost your data). You could simply grow it by allocating a bigger copy, copy it inside, and redefine the pointer, e.g.
{ size_t newnbelem = 3*nbelem/2+10;
char**oldarr = arr;
char**newarr = calloc(newnbelem, sizeof(char*));
if (!newarr) perror("bigger calloc"), exit(EXIT_FAILURE);
memcpy (newarr, oldarr, sizeof(char*)*nbelem);
free (oldarr);
arr = newarr;
}
Don't forget to compile with gcc -Wall -g on Linux (improve your code till no warnings are given), and learn how to use the gdb debugger and the valgrind memory leak detector.
In c you can not allocate an array of string directly. You should stick with pointer to char array to use it as array of string. So use
char* strarr[length];
And to mentain the array of characters
You may take the approach somewhat like this:
Allocate a block of memory through a call to malloc()
Keep track of the size of input
When ever you need a increament in buffer size call realloc(ptr,size)
I know it could be done using malloc, but I do not know how to use it yet.
For example, I wanted the user to input several numbers using an infinite loop with a sentinel to put a stop into it (i.e. -1), but since I do not know yet how many he/she will input, I have to declare an array with no initial size, but I'm also aware that it won't work like this int arr[]; at compile time since it has to have a definite number of elements.
Declaring it with an exaggerated size like int arr[1000]; would work but it feels dumb (and waste memory since it would allocate that 1000 integer bytes into the memory) and I would like to know a more elegant way to do this.
This can be done by using a pointer, and allocating memory on the heap using malloc.
Note that there is no way to later ask how big that memory block is. You have to keep track of the array size yourself.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv)
{
/* declare a pointer do an integer */
int *data;
/* we also have to keep track of how big our array is - I use 50 as an example*/
const int datacount = 50;
data = malloc(sizeof(int) * datacount); /* allocate memory for 50 int's */
if (!data) { /* If data == 0 after the call to malloc, allocation failed for some reason */
perror("Error allocating memory");
abort();
}
/* at this point, we know that data points to a valid block of memory.
Remember, however, that this memory is not initialized in any way -- it contains garbage.
Let's start by clearing it. */
memset(data, 0, sizeof(int)*datacount);
/* now our array contains all zeroes. */
data[0] = 1;
data[2] = 15;
data[49] = 66; /* the last element in our array, since we start counting from 0 */
/* Loop through the array, printing out the values (mostly zeroes, but even so) */
for(int i = 0; i < datacount; ++i) {
printf("Element %d: %d\n", i, data[i]);
}
}
That's it. What follows is a more involved explanation of why this works :)
I don't know how well you know C pointers, but array access in C (like array[2]) is actually a shorthand for accessing memory via a pointer. To access the memory pointed to by data, you write *data. This is known as dereferencing the pointer. Since data is of type int *, then *data is of type int. Now to an important piece of information: (data + 2) means "add the byte size of 2 ints to the adress pointed to by data".
An array in C is just a sequence of values in adjacent memory. array[1] is just next to array[0]. So when we allocate a big block of memory and want to use it as an array, we need an easy way of getting the direct adress to every element inside. Luckily, C lets us use the array notation on pointers as well. data[0] means the same thing as *(data+0), namely "access the memory pointed to by data". data[2] means *(data+2), and accesses the third int in the memory block.
The way it's often done is as follows:
allocate an array of some initial (fairly small) size;
read into this array, keeping track of how many elements you've read;
once the array is full, reallocate it, doubling the size and preserving (i.e. copying) the contents;
repeat until done.
I find that this pattern comes up pretty frequently.
What's interesting about this method is that it allows one to insert N elements into an empty array one-by-one in amortized O(N) time without knowing N in advance.
Modern C, aka C99, has variable length arrays, VLA. Unfortunately, not all compilers support this but if yours does this would be an alternative.
Try to implement dynamic data structure such as a linked list
Here's a sample program that reads stdin into a memory buffer that grows as needed. It's simple enough that it should give some insight in how you might handle this kind of thing. One thing that's would probably be done differently in a real program is how must the array grows in each allocation - I kept it small here to help keep things simpler if you wanted to step through in a debugger. A real program would probably use a much larger allocation increment (often, the allocation size is doubled, but if you're going to do that you should probably 'cap' the increment at some reasonable size - it might not make sense to double the allocation when you get into the hundreds of megabytes).
Also, I used indexed access to the buffer here as an example, but in a real program I probably wouldn't do that.
#include <stdlib.h>
#include <stdio.h>
void fatal_error(void);
int main( int argc, char** argv)
{
int buf_size = 0;
int buf_used = 0;
char* buf = NULL;
char* tmp = NULL;
char c;
int i = 0;
while ((c = getchar()) != EOF) {
if (buf_used == buf_size) {
//need more space in the array
buf_size += 20;
tmp = realloc(buf, buf_size); // get a new larger array
if (!tmp) fatal_error();
buf = tmp;
}
buf[buf_used] = c; // pointer can be indexed like an array
++buf_used;
}
puts("\n\n*** Dump of stdin ***\n");
for (i = 0; i < buf_used; ++i) {
putchar(buf[i]);
}
free(buf);
return 0;
}
void fatal_error(void)
{
fputs("fatal error - out of memory\n", stderr);
exit(1);
}
This example combined with examples in other answers should give you an idea of how this kind of thing is handled at a low level.
One way I can imagine is to use a linked list to implement such a scenario, if you need all the numbers entered before the user enters something which indicates the loop termination. (posting as the first option, because have never done this for user input, it just seemed to be interesting. Wasteful but artistic)
Another way is to do buffered input. Allocate a buffer, fill it, re-allocate, if the loop continues (not elegant, but the most rational for the given use-case).
I don't consider the described to be elegant though. Probably, I would change the use-case (the most rational).