TTF_OpenFont fails on Nth attempt - c

I'm trying to make a game in C using SDL_ttf to display the score every time the diplay is refreshed. The code looks like :
SDL_Surface *score = NULL;
TTF_Font *font;
SDL_Color color = { 255, 255, 255 };
font = TTF_OpenFont( "/home/sophie/Bureau/snake/data/ubuntu.ttf", 28 );
if (font == NULL) {
printf("%s\n", TTF_GetError());
}
score = TTF_RenderText_Solid( font, "score to display", color );
SDL_BlitSurface( score, NULL, screen, NULL );
SDL_Flip(screen);
When I launch the game, everything works properly, but after a while the game crashes and I get the following error :
Couldn't open /home/sophie/Bureau/snake/data/ubuntu.ttf
libgcc_s.so.1 must be installed for pthread_cancel to work
Abandon (core dumped)
I tried different fonts but I still have this problem.
Then I used a counter in the main loop of the game and found that the game always crashes after the 1008th time, regardless of the speed I wanted it to work at (in snake everything goes faster when you score points).
I don't know where does the problem comes from, nor what exactly does the error message mean.
Please tell me if you have any ideas, or if my question is poorly formulated. I looked on several forums and found nothing corresponding to my case, I could use any help now !
Thanks in advance

It looks like you're repeatedly opening the font every time you go through this function:
font = TTF_OpenFont( "/home/sophie/Bureau/snake/data/ubuntu.ttf", 28 );
While it may not be in the main game loop as Jongware suspected, you mentioned that after 1008 executions through this code path, the code crashes.
What is happening is that some resource is being leaked. Either the resource needs to be released by calling TTF_CloseFont() or (more efficient) hold onto the handle after the first time you open it and re-use it each time. Use a static declaration for the font and initialize to NULL:
static TTF_Font *font = NULL;
Then, if it hasn't been opened yet, open it:
if (!font) {
font = TTF_OpenFont( "/home/sophie/Bureau/snake/data/ubuntu.ttf", 28 );
}
This will initialize font the first time while subsequent iterations over the code will not unnecessarily re-do the process and leak the resource.
You mentioned that the code crashes after 1008 times through this function. That's pretty close to 1024. As memory serves, Linux has a limit of 1024 file handles per process (this is probably tunable in the kernel but I have run into this limitation in debugging resource leaks before). There are probably 16 other file handles open by your process and then 1 process being leaked by each invocation of TTF_OpenFont. Once you go above 1024, boom.
You can check the number of open file handles of a particular process (<pid>) by inspecting the number of file descriptors in /proc/<pid>/fd/.

Related

Why would the read system call stop working halfway through a program?

I'm working on an assignment that involves creating files and manipulating characters within them using what the lecturer describes as "File and System I/O calls" in C.
Specifically, I am using open, creat, read, write, lseek, close, and unlink.
Without revealing too much and violating academic integrity, essentially the assignment just entails creating files, copying characters between them, changing the characters, etc.
All of this was going perfectly until a certain point of the program after which read just... Wouldn't work. It doesn't matter what file I am accessing, or what other calls I put before it- for instance, I have tried closing and re-opening a file before trying to read, writing before reading (worked perfectly, put the characters right at the file position the lseek intended), etc.
I have checked the returns of all previous commands, none are giving errors other than the read, which is giving me errorno 9. Having looked this up, it appears to refer to having an incorrect file descriptor, but this doesn't make sense to me as I can use the same fid for any other command. Using ls -l, I confirmed that I have read and write permission (groups and public do not, if that helps).
I am at a total loss of where to go troubleshooting from here, any help would be immensely appreciated. Here is the code snippet in question:
readStatus = lseek(WWWfid,500,0);
if (readStatus<0) {
printf("error with lseek");
return 0;
}
/*printf("Read status: %i\n", readStatus);/*DEBUG*/
writeStatus = write(WWWfid, "wtf", 3);
if (writeStatus<0) {
printf("error with write");
return 0;
}
readStatus = read(WWWfid, buffer, 26);
int errorNum = errno;
/*buffer[27] = '\0';*/
if (readStatus<0) {
printf("error with read before loop, error %i\n", errorNum);
return 0;
}
I can likely include more without invoking the wroth of my uni but I'd prefer not to- also seems likely to be irrelevant given that all proceeding code appears to be functioning correctly.
Thanks for reading, please let me know if you have any insight at all

How can I have skinnier pthreads?

I have a really basic ncurses program to monitor machine statistics and launch remote xterms. It just sits on a window all day and helps me choose a not-heavily-loaded machine to work on. It works fine, and I love it dearly. But it's really fat. Much fatter than it needs to be, I think.
The program basically is as follows:
void * run(void * task) {
// once per minute:
popen( /* stats checking command */ )
// save output to global var
pclose
}
int main() {
// setup ncurses with halfdelay
for ( /* each machine */ )
pthread_create(somethread, NULL, run, (void *)somestruct);
while ( ( c = getch() ) != 'q' )
for ( /* each machine */ )
// print machine stats
// maybe launch an xterm
// die gracefully
}
And as stated above, it works just fine. The problem is that each thread has all the ncurses baloney tucked in private memory leading to one very fat process with a boatload of wasted bits.
The question, then, is this: how can I re-write or re-arrange this program so that each pthread doesn't carry around all the unnecessary ncurses stuff?
Side-question: You'll have to really sell me on it, but does anyone know of a better method than ncurses to do this? I want the stats on fixed positions in the terminal window, not scrolling text.

Can't write to a file when running my code optimized

I have a program that writes data to a binary file, it works when I run it in Visual Studio 2013 in Debug mode (no optimization), but when I run it in Release mode, with Maximize Speed enabled, it doesn't work (the file becomes empty)...
Can you tell me why it might not work?
EDIT:
Dr. Memory log of running the application in Release mode, if you see something alarming, please tell me: http://pastebin.com/5s4Z51ZV
Which errors might cause the problem?
Also, should I work on fixing every single one of the errors? or are some of them "false positives"?
EDIT:
After debugging the optimized code via this guide: http://msdn.microsoft.com/en-us/library/vstudio/606cbtzs%28v=vs.100%29.aspx , I found something very weird was happening when I generate a huffman tree (from a priority queue of characters), this is my code:
HNode * generateHuffmanTree(Queue * queue) // generates a huffman tree from a queue of a file's characters.
{
HNode * root = (HNode *) calloc(1, sizeof(HNode));
root->left = dequeue(queue); // gets the two smallest-amount characters
root->right = dequeue(queue); // and puts them into left and right of the root.
root->character = '\0';
root->value = root->left->value + root->right->value;
if (isQueueEmpty(queue)) return root; // end condition, if it's the only thing left.
enqueue(queue, root); // puts the root back in the queue so it can be a part of the process in the next iteration
#ifdef debug
printQueue(queue);
#endif
generateHuffmanTree(queue); // runs the operation again, now with the new root in the queue.
}
I can see in the debugger that the problem is not in queue as it comes in as it should, but it seems to ignore my declaration of root, then when I try to do root->left it overwrites the data in queue. Anyone know why this might happen and how to find a work around or fix it? Or is it even not the problem?
I figured out what caused the problem. It had nothing to do with the file specifically, I had a function initMap that creates a struct: Map m, initializes it with initial values and returns &map to another function. I suspected this might be a problem because it will get popped out of the stack and then the pointer will be to nothing. But since it worked while I tested it (in Debug mode) I left it alone. But appearently it doesn't work. So what I did is Map * map = (Map *) calloc(1, sizeof(Map)); and it worked.
Thanks to mafso and Kalsai for helping me figure it out.

video capturing with opencv

I am coding an app in C for windows using openCV. I want to capture video from the webcam and show it in a window.
The app is almost finished but it doesn't work properly. I think it's because of the cvQueryFrame() that alwasy returns NULL and I don't know why. I tried capturing some frames before going into the while but didn't fix the problem.
The compiler doesn't show me any error. It's not a compiling problem but an execution one. I debugged it step by step and in the line
if(!originalImg) break;
it allways jumps out of the while. That's why the app doesn't remain in execution. It opens and closes very fast.
Here's the code:
void main()
{
cvNamedWindow("Original Image", CV_WINDOW_AUTOSIZE);
while (1)
{
originalImg = cvQueryFrame(capture);
if(!originalImg) break;
cvShowImage("Original Image", originalImg);
c = cvWaitKey(10);
if( c == 27 ) break;
}
cvReleaseCapture(&capture);
cvDestroyWindow("Original Image");
}
Let's see if someone have some idea and can help me with this, thanks!
Assuming the compilation was ok (included all relevant libraries), it may be that the camera has not been installed properly. Can you check if you are able to use the webcam otherwise (using some other software)
If the compilation is actually the issue, please refer to the following related question:
https://stackoverflow.com/a/5313594/1218748
Quick summary:
Recompile opencv_highgui changing the "Preprocesser Definitions" in the C/C++ panel of the properties page to include: HAVE_VIDEOINPUT HAVE_DSHOW
There are other good answers that raise some relvant good points, but my gut feeling is that the above solution would work :-)
It seems you have not opened capture.
Add in the beginning of main:
CvCapture* capture = 0;
capture = cvCaptureFromCAM(0);

How can I make the printer work in C in MS VC++ Express edition?

I am using VC++ 2008 express edition for C. When I try to run this:
/* Demonstrates printer output. */
#include <stdio.h>
main()
{
float f = 2.0134;
fprintf(stdprn, "This message is printed.\n\n");
fprintf(stdprn, "And now some numbers:\n\n");
fprintf(stdprn, "The square of %f is %f.", f, f*f);
/* Send a form feed */
fprintf(stdprn, "\f");
}
I get four of these errors: error C2065: 'stdprn' : undeclared identifier.
On this forum, they wrote that it works to define the printer as follows:
FILE *printer;
printer = fopen("PRN", "w");
EDIT
It builds with a warning that fopen is unsafe. When it runs the error appears:
Debug Assertion fails.
File: f:\dd\vctools\crt_bld\self_x86\crt\src\fprintf.c
Line: 55
Expression: (str != NULL)
The stdprn stream was an extension provided by Borland compilers - as far as I know, MS have never supported it. Regarding the use of fopen to open the printer device, I don't think this will work with any recent versions of Windows, but a couple of things to try:
use PRN: as the name instead of PRN (note the colon)
try opening the specific device using (for example) LPT1: (once again, note the colon). This will of course not work if you don't have a printer attached.
don't depend on a printer dialog coming up - you are not really using the WIndows printing system when you take this approach (and so it probably won't solve your problem, but is worth a try).
I do not have a printer attached, but I do have the Microsoft XPS document writer installed, s it shoulod at least bring up the standard Windows Print dialog from which one can choose the printer.
No. It wouldn't bring up a dialogue. This is because you are flushing data out to a file. And not going through the circuitous Win32 API.
The print doesn't work because the data is not proper PDL -- something that the printer could understand. For the print to work fine, you need to push in a PDL file, with language specific constructs. This varies from printer to printer, a PS printer will need you to push in a PostScript snippet, a PCL -- a PCL command-set and in case of MXDW you will have to write up XML based page description markup and create a zip file (with all resources embedded in it) i.e. an XPS file to get proper printout.
The PDL constructs are important because otherwise the printer doesn't know where to put the data, which color to print it on, what orientation to use, how many copies to print and so on and so forth.
Edit: I am curious why you are doing this. I understand portability is probably something you are trying to address. But apart from that, I'd like to know, there may be better alternatives available. Win32 Print Subsytem APIs are something that you ought to lookup if you are trying to print programmatically on Windows with any degree of fidelity.
Edit#2:
EDIT It builds with a warning that fopen is unsafe.
This is because MS suggests you use the safer versions nowadays fopen_s . See Security Enhancements in the CRT.
When it runs the error appears:
Debug Assertion fails. File: f:\dd\vctools\crt_bld\self_x86\crt\src\fprintf.c Line: 55
Expression: (str != NULL)
This is because fopen (whose return value you do not check) returns a NULL pointer. The file open failed. Also, if it did succeed a matching fclose call is called for.
There's no such thing as stdprn in ANSI C, it was a nonstandard extension provided by some compilers many years ago.
Today to print you have to use the specific APIs provided on your platform; to print on Windows you have to use the printing APIs to manage the printing of the document and obtain a DC to the printer and the GDI APIs to perform the actual drawing on the DC.
On UNIX-like OSes, instead, usually CUPS is used.
You can substitute the printer using this command with net use, see here on the MSDN kb
NET USE LPT1 \\server_name\printer_name
There is an excellent chapter on printing in DOS using the BIOS, ok, its a bit antiquated but interesting to read purely for nostalgic sake.
Onto your problem, you may need to use CreateFile to open the LPT1 port, see here for an example, I have it duplicated it here, for your benefit.
HANDLE hFile;
hFile = CreateFile("LPT1", GENERIC_WRITE, 0,NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
// handle error
}
OVERLAPPED ov = {};
ov.hEvent = CreateEvent(0, false, false, 0);
char szData[] = "1234567890";
DWORD p;
if (!WriteFile(hFile,szData, 10, &p, &ov))
{
if (GetLastError() != ERROR_IO_PENDING)
{
// handle error
}
}
// Wait for write op to complete (maximum 3 second)
DWORD dwWait = WaitForSingleObject(ov.hEvent, 3000);
if (dwWait == WAIT_TIMEOUT)
{
// it took more than 3 seconds
} else if (dwWait == WAIT_OBJECT_0)
{
// the write op completed,
// call GetOverlappedResult(...)
}
CloseHandle(ov.hEvent);
CloseHandle(hFile);
But if you insist on opening the LPT1 port directly, error checking is omitted...
FILE *prn = fopen("lpt1", "w");
fprintf(prn, "Hello World\n\f");
fclose(prn);
Hope this helps,
Best regards,
Tom.

Resources