This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
[EDIT:]
I have removed a lot of code now. And I have reduced it to a more straight forward question.
Is it OK, to pass this variable...
char Record_Info[file_length + 1];
to another function, like this:
listdir(tempdesc, 0, sockid, Record_Info);
which uses this header:
int listdir(char *dirname, int lvl, int sockid, char Record_Info[])
And the listdir() can call its-self many times?
.
* Orig Question *
I was wondering if another set of eyes can look at this please. It was working, but I added some more code (probably more sprintf, near the bottom) and now a Segmentation fault occurs.
This program creates/sends the web page, correctly, but crashes when it returns from the send_recordings_list() function back to the parsing_request() function. I don't think its necessary to understand how its formatting the data from the file, but I included that bit anyway.
For the most part, I'm using static variables, and when I attempt to free() any thing, it causes another seg fault, or gcc lib fault. Also I am unsure if passing the variables between the functions() might be causing the issue?
Also worth mentioning, a different function (not shown in here) sends out a web page which is about 4MB, I can call this one many times and it does not crash. I have placed a few // ****** at some lines which might be of interest?
Oh yes, I have not done much standard error handling yet... (I'll do it later), so assume its a spherical chicken in a vacuum.
.
So it starts at parsing_request()
goes to send_recordings_list()
goes to listdir() . (this calls its self many times)
back to send_recordings_list()
. (seg fault here)
back to parsing_request()
.
I'm hoping some will go 'ahh i see what you did fool......'
Embedded Linux 2.6.27, GCC 4.2.4, 32MB Ram
void parsing_request(int sockid, char *buff)
{
char *res_line=malloc(MAXLINE), path[MAXLINE], *line;
// Cut code
if (strcmp(line, "/recordings_body.htm") == 0)
{
send_recordings_list (sockid); // ****** IT GOES HERE 1st ******
return;
}
free (res_line);
return;
}
int send_recordings_list(int sockid)
{
int hnd;
int hnd2;
char tempdesc[MAX_PATH_LENGTH];
// Copy all of the data <1 MiB (Slow reading)
int file_length = lseek (hnd2, 0, SEEK_END);
char Record_Info[file_length + 1]; // ******
lseek (hnd2, 0, SEEK_SET);
read (hnd2, Record_Info, file_length);
close (hnd2);
// Cut out code
del_file_cnt = 0;
sprintf (tempdesc, "%s/Recordings", TOPPY_DIR);
listdir(tempdesc, 0, sockid, Record_Info); // ***** Major 2nd call here
return 0;
}
int listdir(char *dirname, int lvl, int sockid, char Record_Info[])
{
int i;
DIR* d_fh;
struct dirent* entry;
char longest_name[4096];
char tempdesc[4096], morespace[128];
int row_col;
char chan_name[128], alt_name[128], desc[500], category[128], rec_time[14], start_time[14], end_time[14];
char trim_file_name[128], trim_file_name2[128], trim_alt_name[128], file_links[1535];
char logo[128];
int length, u_score, dot;
char *looky_pos1, *looky_pos2;
int is_match;
struct tm tm_rec, tm_start, tm_end;
time_t tim_rec, tim_start, tim_end;
// Cut out code
return 0;
}
Sorry, this is a hopeless mess. Learn how to use Linux tools like valgrind and gdb. Check carefully that the memory you request is eventually freed once and after its use is done. Check that you don't pass pointers to local variables out of functions. Check that your strings are long enough to accomodate the data expected (or check as part as your as of now nonexistent error handling).
One debugging strategy that is suprisingly effective is the Teddy Bear Consultant: Get a teddy bear and explain your problem to it step by step. Only if that doesn't help is a real human warranted. [It works because sorting out your understanding to explain it forces you to really think it through.]
After looking quickly at your code, you have two options:
Learn how to handle errors, how to manage resources and how to avoid global variables
Use a programming language which does it for you
Both will take a long time but using the second approach, you will be much more productive.
I suggest to try to implement the above with Python just to get a feeling.
Answering your most recent post, asking if you can pass the character value into the function... I don't understand what you're trying to do. In the function prototype you have the final parameter as a char variable_name[], are you trying to pass a array in? If so, why not use a pointer?
so the prototype would like like:
int listdir(char *dirname, int lvl, int sockid, char* Record_Info);
Passing by reference always tends to give you a little bit more control, whether you want it or not. Are you trying to pass in a specific element of an array?
Related
I think my english is just to bad to understand the other articles about this. But anyway:
I just thought i could write a program (in C), that can store a set of cards.
Not complicated, just store values and names of cards and print them out.
I'm a beginner in C, and because i'm in the section "Strings in Structures" in my Book, i wanted to try out structures on my own. This is my Code so far:
#include <stdio.h>
struct card
{
int value;
char name[];
};
int main(void)
{
const struct card heart[13] = { {2,"two"}, {3,"three"}, {4,"four"}, {5,"five"}, {6,"six"}, {7,"seven"}, {8,"eight"}, {9,"nine"}, {10,"ten"}, {11,"jack"}, {12,"queen"}, {13,"king"}, {14,"ace"} };
int i;
for (i = 0; i < 13; ++i)
{
printf("The card heart-%s has the value of %i", heart[i].name, heart[i].value);
}
return 0;
}
I just wanted to test if it works, so i just wrote the heart-cards in the code. If i want to compile this file, my compiler (gcc/mingw) hits me with 26 errors. It says:
"(near initialization of heart[0])"
"non static initialization of a flexible array member"
I don't really understand this. In the book, everything works as expected. I tried to rebuild the code in the book and changing the names, but it doesn't work. I think it's a problem with the strings, because if i use integers only, everything works.
In already read in another post, that every string should be allocated manually, and there was a code example, but i don't know what all the lines should mean, and i want understand what my code does, so i don't copy + paste.
Could you explain me why this doesn't work?
PS: I am writing currently in windows, so please don't use bash commands to explain or something like that.
I am also german and my english is not the "yellow of the egg", try to explain without using complex 'sentence builds' (i hope you know what i mean :D) and unusual words.
Thanks for all help!
You need to create some space for the name of each card. Easiest way to do this would be to change your struct card definition to something like:
struct card
{
int value;
char name[16]; // doesn't have to be 16, but make sure it's large enough to hold each card name plus a '\0' terminator
};
The prior answers suggest allocating a fixed length for your names. This has limitations and even dangers. It is always a good idea to avoid it all together.
e.g. You want to alter the name during the game, e.g. "Ace (Trump Card)" but that might be both too long even worse overwrite memory. (Many of the known vulnarabilities in code are caused by buffer overruns)
You are also building in a limitation; What if your game needs translating into another language?
By using pointers, you don't need to resort to either variable length structures or fixed string lengths.
You also add the ability to add API access functions that set data, allowing checks before it's written, preventing buffer overruns.
Instead of using character array (aka strings) you should use pointers in your structures. If you follow the link at the bottom I take this further and use pointers to the structures themselves.
As the pointer storage size never changes your names can be of any length and even altered later, perhaps as the game progresses.
Your card could look something like
typedef struct card
{
int value;
char * name;
}
Now the initial assignment can be done like this
card_t card_ace = {14, "Ace"};
And the values are not fixed (unless that is what you want, then you make them const).
card_ace.value = 200;
card_ace.name = "Trump card";
or an array of cards like this
card_t suit_hearts[] = {{2,"two"}, {3,"three"}, {4,"four"}, {5,"five"}, {6,"six"}, {7,"seven"}, {8,"eight"}, {9,"nine"}, {10,"ten"}, {11,"jack"}, {12,"queen"}, {13,"king"}, {14,"ace"}}
Even better make the whole thing using pointers
typedef card_t * cards_t;
cards_t mysuit = &(card_t){2,"two"}, &(card_t){3,"three"}, ...
Perhaps consider makeing the suit a structure.
typedef struct
{
char * name;
card_t ** cards;
} suit_t;
typedef card_t * cards_t[];
suit_t mysuit = {
.name = "Hearts",
.cards = (cards_t){&(card_t){2,"two"}, &(card_t){3,"three"},....}
}
* For a fully working example of the latter, demonstrating using arrays of pointers to sidestep the limitations of variable length members of fixed arrays, see this gist on github
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
How do I dynamically create an array of struct in a function in C?
The struct:
typedef struct Track {
char artist[LONGSTR];
char file[LONGSTR];
int id;
int isAlbum;
char name[LONGSTR];
int pos;
char title[LONGSTR];
int time;
} Track;
The function:
int
processplaylist (struct Track** tracks, char* resp)
{
//count the tracks to return
//allocate space for the resulting tracks
*tracks = mem_alloc (count * sizeof (struct Track));
//process each track
return count;
}
And the usage:
char playliststr[] = "file: some-mp3\nTitle: Dire Straits - Romeo And Juliet\nName: TheRadio\nPos: 0\nId: 12\nOK\n"
struct Track* tracks = NULL;
int count = mpd_processplaylist(&tracks, playliststr);
Within the function the tracks are nicely processed and upto the return statement tracks points to the right location to get to the tracks. Most questions I have seen are about arrays to values, not structs.
This answer returns an array of structs, but I would like to return the count (question of style) and return the array through the parameter.
What is going wrong? After the function returns, count has the right value and tracks is still NULL.
As the not so nice people pointed out by down voting the question, the question is too broad and vague. I apologize for that, I was desperate.
As the nice people in the comments confirmed, the code is correct. Even though the debugger showed that just before the return statement everything was OK and after returning to the usage it was not.
By commenting out code lines and logging a lot, there are two things to note.
Within the function, you must refer to the individual tracks as (*tracks + i) or, for example, (*(*tracks + i)).file. Indeed, not shown in the sample code. I had tried *(tracks + i), &tracks[i] and tracks + i, which in the debugger all seemed to work and did not cause immediate errors. I guess the code messed up memory that only came out after the return.
Outside the function, in the usage, you refer to the tracks as an array, as tracks[i] or, for example, tracks[i].file.
I hope that at least my answer helps.
I have a function that takes a string and cuts out a some parts of it.
The function does its thing a couple of times until, all of a sudden, the same malloc line that worked fine, crashes with No source available for "0xb7e88a81" error.
Tried to clear out every thing to make sure I'm not sending NULL length or whatever, but still no luck.
It worked at least once (debugged it) but on the second or third iteration it crashes.
char *removeOffsetFromLabel (char *label) {
char* labelWithoutOffset;
int i;
labelWithoutOffset = malloc(strlen(label));
........
The crash happens on the malloc line (when trying to move to the next line).
strlen(label) = 7 (checked it)
Any ideas ? I'm using GCC compiler on Eclipse (Ubuntu).
Per FoggyDay's request this is the whole function:
char *removeOffsetFromLabel (char *label) {
char* labelWithoutOffset;
int i;
labelWithoutOffset = (char*)malloc(strlen(label) + 1);
i = 0;
while (label[i] != '\0' && label[i] != OPENING_BRACKET_ASCII_CODE) {
labelWithoutOffset[i] = label[i];
i++;
}
labelWithoutOffset[i] = '\0';
return labelWithoutOffset;
}
I do free up "labelWithoutOffset" outside of the function before calling it again.
I wish I could mark all of your answers with V sign to indicate it solved the issue since you've been most helpful.
After digging in I made two changes to my code and things seem to be working fine so far:
Removed two "free" commands that were used on an already freed up pointers (dumb mistake)
Added "pointer = NULL" after every free (just to be on the safe side)
Again, I thank all of you for showing me other issues I had in my code.
StackOverflow ROCKS !
1) As already mentioned above, "malloc()" MUST BE "strlen()+1":
char *removeOffsetFromLabel (char *label) {
char* labelWithoutOffset = (char *)malloc(strlen(label)+1);
2) Since this didn't solve the problem, we also need to look at:
a) is "label" valid when we call strlen()?
b) do you have any code that might be overwriting "labelWithoutOffset" somewhere else - after you've allocated it in one call, and before you allocate it again in a different call?
SUGGESTIONS:
a) Add this code (or better, look at "label" in your debugger):
char *removeOffsetFromLabel (char *label) {
fprintf (STDERR, "label=%s\n", label);
fprintf (STDERR, "strlen(label)=%d\n", strlen(label);
char* labelWithoutOffset = (char *)malloc(strlen(label)+1);
b) Post some more code from "removeOffsetFromLabel()" - maybe we can see where the variable might be "getting stepped on".
PS:
If you're feeling ambitious, check out my link to the Valgrind tutorial above it.
But for "quick results", please try suggestions 1) and 2); and let us know how it goes.
if strlen(label) is indeed 7, than it's not strlen() but malloc() itself that crashes.
If malloc() crashes, that probably means malloc()'s internal housekeeping was destroyed earlier/elsewhere (by a pointer gone crazy).
Bugs like this are hard (hardest) to find since you can't tell where they are because the crash is likely happening long after the cause.
You might want to look into Valgrind usage.
Scratch that.
i dont understand whatever function type that is there, but to my knowledge of malloc(); and strings, since label is an array you should send it like this
void funcCall(int *)
main()
{
funcCall(label)
}
funcCall(int funcLabel[])
{
}
hope this helps.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I have spent ages trying to figure out what is the problem with the following program:
typedef struct user {
char host[40];
int order;
} user;
typedef struct data {
user userdat;
} data;
int read_user (char *datname, user *userdat) {
...
fscanf (datin, "%s", &userdat->host);
fscanf (datin, "%d", &userdat->order);
//1
printf ("%d\n", userdat->order);
...
}
void init_data (data *dat) {
init_userdat (&dat->userdat);
}
void init_userdat (user *userdat) {
*userdat->host = "127.0.0.1";
userdat->order = 0;
}
int user_print (int i, data *dat) {
//2
printf ("%d\n", dat->userdat.order);
}
int main(int argc, char *argv[]) {
...
data dat;
init_data (&dat);
read_user (datname, &dat->userdat);
user_print (&dat);
}
The program is very simplified to highlight the relevant sections. What happens is that the first print statement (//1) outputs the value correctly, while the second (//2) does not - it outputs something that looks like a possible memory location.
I have tried numerous combinations of accessing the stored variable, but I just can't crack it. Any help would be appreciated.
Edit1: Fixed up a couple of non essential errors in code (not relating to pointers or structs)
Final Edit: Thank you all for your help. The issue that Arun Saha pointed out was indeed in the original code and is now fixed. However, the problem of printing two different strings persisted. Your assurance that the code should otherwise compile and work led me to discover the true culprit - I was not properly initializing another part of the otherwise complex struct and this resulted in overwriting of the user.order variable.
The following line does not do what it appears to do :-)
*userdat->host = "127.0.0.1";
userdata->host is a pointer to the first character in the host[40] array. The above statement would copy only one character from the source string ("127.0.0.1"). To copy the entire string, use the standard library function stncpy()
strncpy( & userdata->host[ 0 ], "127.0.0.1", 40 );
In your main function, when you invoke read_user (datname, &dat->userdat);, I feel there should be a compilation issue. This should be actually read_user (datname, &dat.userdat); as dat is not a pointer, but an object itself.
With this change and Arun's previous recommendation, I have tried your program and it works.
I was recently on The Daily WTF when I came across this old post. In it the author mentions that one of the programmers changed this code:
int main (int argc, char **argv)
{
int x;
char data_string[15];
...
x = 2;
strcpy(data_string,"data data data");
...
}
To this code:
int main (int argc, char **argv)
{
int x = 2;
char data_string[15] = "data data data";
...
}
The author goes on to mention:
[the coder] changed every single variable to be initiated on the stack
For the life of me I cannot see how this change could be harmful, and I am worried that it is a lapse in my C knowledge. What is the WTF?
I don't think the stack initialization was the problem. He was supposed to be looking for a hard-to-find memory leak, but he decided to do the initialization change instead on thousands of C files.
Although, as mentioned on wikipedia, "uninitialized variables [are] a frequent cause of bugs". You eliminate the potential for use of uninitialized variables if you take care of it at declaration. But doing that conversion to a few thousand files probably wasn't the most efficient way to find and solve the real problem.
i think the new code is better. Except I would have gone
char data_string[] = "data data data";
The only way this is worse is that it's possible that the older code never initialized (or used) the value in some code paths.
The other problem is this
char data_string[99] = "data data data";
Will initialize 99 characters rather than just the first 15. which makes this
char data_strings[99] = "";
a lot more expensive than this
char data_strings[99];
data_strings[0] = 0;
Of course, if the buffer really only needs to be big enough to hold "data data data",
then this is better
char data_string[] = "data data data";
But that makes you wonder whether it was ever necessary to copy the string into a stack variable at all.