Value in C variable disappears - c

I have a C program that is giving me trouble. It is a plugin for the X-Plane flight simulator. You can view the whole code here. The basic function is pulling some information from curl, running and recording information about a flight, and then finally compiling a report of the flight.
The problem is that there is one variable that is misbehaving. I declare it at the beginning of the code because it is needed across multiple functions.
char fltno[9];
The content is set using a plugin function to get the value from a text box. It takes the value from the FltNoText widget, 8 characters long, and assigns it to the fltno variable.
XPGetWidgetDescriptor( FltNoText, fltno, 8);
I build some messages using the following method that include the fltno variable.
messg = malloc(snprintf(NULL, 0, "Message stuff %s", fltno) + 1);
sprintf(messg, "Message stuff %s", fltno);
This works just fine throughout the running of the program. Right up until the last time it is needed. This is the section that begins with:
if (inParam1 == (long)SendButton)
This will run at the end. When running this section, the fltno variable returns no text. There are many other variables which I am using in the same way, and they all seem to work fine. I ran the program over a short flight and it worked fine, but the two times I have run it on a longer flight, the variable has returned blank in that section.
Let me know if I need to explain more. You can probably tell I haven't written much C so suggestions are appreciated.
More Info
It was suggested that the adjacently decalared variables could be overflowing into fltno.
The Ppass[64] variable is copied from Ppass_def, which is set in the code and is definitely smaller than 64.
strcpy(Ppass, Ppass_def);
The tailnum[41] variable is read from a plugin function.
XPLMGetDatab( tailnum_ref, tailnum, 0, 40 );
Both of these variables are set at the beginning of the program, so it doesn't make sense that fltno only misbehaves at the very end.
Update 1
Thanks for the comments. As suggested by rodrigo, I replaced the longest malloc/sprintf instance with calls to some functions. Not sure if what I did is what you had in mind, but it seems to work at least as well as it did before. You can see the new code on the Github link.
I also did more testing and narrowed down a bit where the problem could be. The fltno variable is fine when run the last time at line 1193, but by the end of the case at line 1278, it is blank. I will try to do more testing later to narrow it down further.
Update 2
After more testing I narrowed it down to line 1292. Before that line the fltno is fine, after that it becomes blank.
strcpy(INlon, dlon);
The dlon variable is declared within the if statement where the switch is.
char dlon[12];
This variable is set every time that section runs, so it's strange that there are no problems until the end. It's set from a function that takes the decimal degrees latitude or longitude and returns a string like "N33 45.9622".
strcpy(dlon, degdm(lon, 1));
The INlon variable is declared at the beginning of the program, and this is the only time it is set.
char INlon[12];
Any ideas about why this part messes up the fltno variable?
Update 3
Thanks for the suggestions about strncpy and an alternative to the double sprintf calls. I changed a few other things and it seems to work now, I will do a full test later to be sure.
A key part that I really should have caught before now is that the latitude/longitude strings were only 12 long, which is too short. When the longitude is over 100 degrees, the string could be "W100 22.5678", which is 12 characters. This caused the end NULL to be cut off and was the source of some of my problems.
char INlat[13];
I noticed this when I was getting something like "W100 22.5678ABC1234" from those variables, where "ABC1234" is the fltno variable.
I used a pointer for dlat to avoid size problems, and use strncpy to make sure to not spill over to other variables.
strncpy(INlat, dlat, sizeof(INlat));
Finally, I found the asprintf function to replace the double instances of sprintf. I understand this won't work on all systems but it's a simple fix for now.
char * purl = NULL;
asprintf(&purl, "DATA1=%s&DATA2=%s", DATA1v1, DATA2);
So thanks for your help in fixing my code (assuming that it's working now). I feel like I knew enough to be able to fix it (once I was pointed in the right direction) but I'm still not sure exactly what was going on. If anyone wants to post an explanation of what was going wrong (as far as you can tell) I would be happy to accept an answer.

Related

Multithreading in C with CLion (Windows)

I have a section of code which is really time-consuming (~2s), and can be executed without the last one have finished.
for (x = last; x <= end && !found; x++) {
found = combine(combinaciones, x, end, &current);
}
Note that combine() it's the function I was talking about. But before the loop starts again (this for it's inside another loop) all the functions must have finished.
Also, combine() receives some arguments, combinaciones it's a pointer, and current an integer (by reference). The integer gets modified over time (and must get modified on the other active functions) and combinaciones it's a linked list (size of which is current-1). The 2nd and 3rd argument are just integers. The return it's a boolean that terminates the loop, but I don't matter if they make some extra operations.
I stress the importance of current. If current is equal to 5, combinaciones's 5th element will be the created, and then current will be 6. I mean that if two functions are allocating memory they souldn't allocate to the same position.
If that can't be done I can make the operations in parallel, and then allocate the memory on the main().
So, I started searching about multithreading and I found <pthread.h>, but it only worked on Linux (not on CLion). I found something caled fork, I don't know either if can be used. Would you tell me a Windows multithreading API, with an example, and the CLion implementation?
The code is huge and I don't think that would help a lot, with I have said should be enought. However, if something is unclear let me know. The code itself it's published on GitHub, but the (few) comments it has are in Spanish.
Thanks for your help!
Using Wsl (as #Singh said) I could use pthread.h. Then I just adapted my code. A very annoying bug that I had was that "IDs" (current variable) were assigned non-continuously (the first thread had "3", and the second one had "2"). I was able to fix it by using a global variable (pthread_mutex_t) and pthread_mutex_lock(), pthread_mutex_unlock(). For more information you can still check my code on GitHub.

Having trouble with a c program that separates strings into paragraphs. sentences and words

The program needs to get input text and an option from the user. At this stage I am currently working on the ap: option which reads a text from the user and appends the corresponding data to the corresponding arrays. (Also I have to input the text with the option as a prefix, e.g. ap:Text, because that is how the bot that tests my program inputs it.).
Here is the code: https://gist.github.com/Kritsos/03d08f29beb97d24eba1cbc4e83962ab
I know it's a bit difficult to follow it so I will try to explain it as better as I can. First of all I know that there are a lot of memory leaks, I will tend to them as soon as I get the 3 functions working. I have tried to dynamically allocate almost everything (that's why I use triple pointers) and I hope that the allocation is correct and not the cause of the problems. The par function is supposed to get a paragraph from the input text which is easy because the input texts is a paragraph on its own so I just copy the text to the paragraph array. Now the sent and word functions are the ones I am having trouble with. Both are based on the same logic. I take the input text from the user, I try to find the ending character( ".!?;" for sentences " " for words), place a '\0' there, copy the string to the corresponding array then do the same thing but instead of checking the whole input text again I start from the position I placed the '\0' + 1.
Your code has numerous errors in it, the critical one that's causing your current crash are lines 8, 32, and 59. All variations on this:
**paragraphs = realloc(**paragraphs, *num_par * sizeof(char *));
You're calling realloc on pointers that were never allocated in the first place.
The lesson here isn't "be careful with pointers" or anything like that, though obviously you should be. The lesson is that tons of indirection becomes difficult to reason about. Rather than try to make a three-star solution work, you should explore a different approach that doesn't require these kinds of code gymnastics.

Backtracking algorithm crashes with hard cases (C)

I am actually making an algorithm that takes as an input a file containing tetriminoses (figures from tetris) and arranges them in smallest possible square.
Still I encounter a weird problem :
The algorithm works for less than 10 tetriminoses (every time) but start crashing with 11, 12... (I concluded that it depends on how complicated the solution is, as it finds some 14 and 15 solutions).
But the thing is, if I add an optimisation flag like -Ofast (the program is written in C) it works for every input I give him no matter how much time it takes (sometimes more than a hour..).
First I had a lot of leaks (I was using double linked list) so I changed for an Int Array, no more leaks, but same problem.
I tried using the debugger but it makes no sense (see picture) :
Debugger says my variables do not exist anymore but all I do is increment or decrement them.
For this example it just stopped while everything is fine (values of variables are correct)
Here is the link of my main function (the one that do the backtracking):
https://github.com/Caribou123/fillitAG/blob/master/19canplace/solve.c
The rest of program (same repository) consist of functions to put tetriminoses in my array, remove them from it, or print the result.
Basically I try placing a tetri, if I have enough space, I place the next one, otherwise I remove the last one and place it to the next available position etc..
Also I first thought that I were trying to place something outside of the Array, so now my Array is way bigger than it should be and filled with -1 for invalid cases (so in the worst case I just rewrite a -1), 0 for free ones, and integers values from 1 to 26 for figures.
The fact that the program works with the flag -Ofast really troubles me, as the algorithm seems to work perfectly, what could cause my program to crash ?
Here is how I tracked the number of recursions, by adding two static variables
And here is the output
(In case you want to test it yourself, use the 19canplace folder, and compile with : gcc *.c libft/libft.a)
Thanks in advance for your time,
Artiom

C - how does sprintf() work?

I'm new to coding in C and was writing a program which needs to create custom filenames that increment from 0. To make the filenames, I use sprintf() to concatenate the counter and file extension like so:
int main(void)
{
// do stuff
int count = 0;
while (condition == true)
{
char filename[7];
sprintf(filename, "0%02d.txt", count) //count goes up to a max of 50;
count++;
//check condition
}
return 0;
}
However, every time
sprintf(filename, "0%02d.txt", count);
runs, count gets reset to 0.
My question is, what does sprintf() do with count? Why does count change after being passed to sprintf()?
Any help would be much appreciated.
EDIT: Sorry, I haven't been too clear with the code in my question - I'm writing the program for an exercise on an online course, and count goes up to a max of 50. I've now changed my code to reflect that. Also, thanks for telling me about %04d, I was using a complicated if statement to determine how many zeroes to add to my filename to make it 3-digit.
Despite the title of the question, this has nothing to do with sprintf(), which probably works as expected, but everything with count.
If count is a global variable (i.e. outside any functions), then it should keep its value between function calls. So that is probably not the case.
If it is a local variable (declared inside the function), then it can have any value, since these lose their value when the function ends and don't get initialized when the function is run again. It can be always 0, but under different circumstances, it can just as well be something else. In other words, the value is more or less undetermined.
To have a local variable keep its value between function calls, make it static.
static int count = 0;
But note that when you stop and run the program again, it will start as 0 again. That means you would possibly overwrite 000.txt, then 001.txt, etc.
If you really want to avoid duplicate file names, you will have to be more sophisticated, and see which files are already there, determine the highest number, and increment that by one. So you don't use a variable, you check the files that already exist. That is far more work, but the only reliable way to avoid overwriting existing files with such numbered file names.
FWIW, I would use something like "00%04d.txt" as format string, so you get files 000000.txt, 000001.txt, etc. which look better in an alphabetically sorted file listing than 000.txt, 001.txt, 0010.txt, 0011.txt, 002.txt, etc. They are also easier to parse for their number.
As Weather Vane noticed, be sure to make your buffer a little larger, e.g.
char filename[20];
A buffer that is too small is a problem. One that is too large is not, unless it is huge and clobbers up the stack. That risk is very small with 20 chars.
I think it is likely the sprintf. "0%02d.txt" is 7 chars. The null at the end of the string will go in the next location, which is likely the count on the stack. On a little endian machine (x86), that likely means the bottom byte of count gets zeroed out in every sprintf().
As other folks said. Make the filename buffer larger.

How to view variables during program execution

I am writing a relatively simple C program in Visual C++, and have two global variables which I would like to know the values of as the program runs. The values don't change once they are assigned, but my programming ability is not enough to be able to quickly construct a text box that displays the values (I'm working in Win32) so am looking for a quick routine that can perhaps export the values to a text file so I can look at them and check they are what they ought to be. Values are 'double'.
I was under the impression that this was the purpose of the debugger, but for me the debugger doesn't run as the 'file not found' is always the case.
Any ideas how I can easily check the value of a global variable (double) in a Win32 app?
Get the debugger working. You should maybe post another question with information about why it won't work - with as much info as possible.
Once you have done that, set a breakpoint, and under Visual C++ (I just tried with 2010), hover over the variable name.
You could also use the watch window to enter expressions and track their values.
If your debugger isn't working try using printf statements wherever the program iterates.
Sometimes this can be a useful way of watching a variable without having to step into it.
If however you wish to run through the program in debug mode set a breakpoint as suggested (in VS2010 you can right click on the line you want to set a breakpoint on).
Then you just need to go to Toolbars -> Debug Toolbar.
I usually like to put #ifdef _DEBUG (or write an appropriate macro or even extra code) to do the printing, and send to the output everything that can help me tracking what the program's doing. Since your variables are never changing, I would do so.
However, flooding the console with lots of values is bad imo, and in such cases I would rely on assertions and the debugger - you should really see why it's not working.
I've done enough Python and Ruby to tell you that debugging a complex program when all you have is a printf, although doable, is extremely frustrating and takes way longer than what it should.
Finally, since you mention your data type is double (please make sure you have a good reason for not using floats instead), in case you add some assertion, remember that == is to be avoided unless you know 100% that == is what you really really want (which is unlikely if your data comes from calculations).

Resources