1

I have an odd problem. When I try to compile the code below, it works without a failure as expected:

#include <iostream>
#include <Windows.h>

int main(){
       FILE *f = fopen("trystl.geo","w");
       fprintf(f,"Merge \"trystl.stl\";");
       fprintf(f,"\n");
       fprintf(f,"Surface Loop(2) = {1};");
       fprintf(f,"\n");
       fprintf(f,"Volume(3) = {2};");
       fclose(f);
       return 0;
}

But when I try to connect this program to a button with FLTK user interface, it gives me an assertion runtime error. The segment of my code:

void UserInterface::cb_m_BtnSTLToGEOConverter_i(Fl_Button*, void*){
    //OnSTLToGEOConvert();
       FILE *f = fopen("trystl.geo","w");
       fprintf(f,"Merge \"trystl.stl\";");
       fprintf(f,"\n");
       fprintf(f,"Surface Loop(2) = {1};");
       fprintf(f,"\n");
       fprintf(f,"Volume(3) = {2};");
       fclose(f);
}
void UserInterface::cb_m_BtnSTLToGEOConverter(Fl_Button* o, void* v){
    ((UserInterface*)(o->parent()->parent()->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_m_BtnSTLToGEOConverter_i(o,v);   
}

When the user presses the button, I want the program to create a file called trystl.geo and perform the operations shown. But when compile and open the program and click the button, it says:

Debug Assertion Failed!

Program: *.......\src\fprintf.c Line 55:

Expression: (str! NULL)

abort retry or ignore...

I'm using Visual Studio 2010.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Emre Turkoz
  • 868
  • 1
  • 23
  • 33
  • 3
    You compare the first snippet to the second as if they are equivalent, but the second contains a separate function with a very suspicious sequence of function result dereferences. I'd focus your efforts there, and come back to us with a less insane [testcase](http://sscce.org/). – Lightness Races in Orbit Aug 20 '11 at 23:37
  • 1
    @Tomalak: still, the `fprintf` part is identical in the two snippets, and it does not depend on any of the parameters, neither `this` (actually, only string literals are used), so in theory it should just work; the only thing that comes to mind for a malfunction of that kind is a stack corruption. – Matteo Italia Aug 20 '11 at 23:56
  • @Matteo: Right, and given the ridiculous dereferences stack/heap corruption (or simply dereferencing the wrong thing) is obviously the issue. Point is, issues with the second snippet almost certainly have utterly nothing at all to do with the first. It's near-offensive that the differences there could be shrugged off so blindly. – Lightness Races in Orbit Aug 20 '11 at 23:59
  • @Italia. That's the point. The function with all "parent()"s is correct. The problem should lie in somewhere different. – Emre Turkoz Aug 21 '11 at 00:00
  • @Emre: then if it lies elsewhere how can we help you? :S – Matteo Italia Aug 21 '11 at 00:06
  • @Italia. With "correct" I meant when you type something simple there, like "std::cout<<"Text";" instead of the fprintf stuff, it gives the output w/o a failure when you press the button. – Emre Turkoz Aug 21 '11 at 00:11
  • @Emre: before using `fprintf`, check if `f` is not `NULL` after the `fopen`: maybe it's just a failure to open the file (this can happen if the current directory of your executable is not writable by an executable with "normal" privileges). – Matteo Italia Aug 21 '11 at 00:16
  • 1
    `((UserInterface*)o->parent()->parent()->parent()->parent()->parent()->parent()->parent()->user_data()))->cb_m_BtnSTLToGEOConverter_i(o,v);` this will give me nightmares :/ (and obviously kills the formatting of SO under FF :D) – Voo Aug 21 '11 at 01:26
  • @italia you're right, that's the case. I can't open the file. But is there no way to do this? – Emre Turkoz Aug 21 '11 at 07:59

2 Answers2

3

The error is simple: Line 55 in fprintf.c in VC++ is _VALIDATE_RETURN( (str != NULL), EINVAL, -1); and str is the FILE* parameter (I've seen better named variables though).

For the curious (I was) _VALIDATE_RETURN is defined as follows:

#define _VALIDATE_RETURN( expr, errorcode, retexpr )                           \
    {                                                                          \
        int _Expr_val=!!(expr);                                                \
        _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) );                       \
        if ( !( _Expr_val ) )                                                  \
        {                                                                      \
            errno = errorcode;                                                 \
            _INVALID_PARAMETER(_CRT_WIDE(#expr) );                             \
            return ( retexpr );                                                \
        }                                                                      \
    }

So better check if your fopen() call succeeds before trying to write to a nonexistant filedescriptor.

Voo
  • 29,040
  • 11
  • 82
  • 156
  • thank you for your help and you're right. my program can't call fopen(). I also tried to initialize the pointer as a global variable, it also didn'T work. I wonder why this is the case. Can't I initialize a new file with GUI or what? – Emre Turkoz Aug 21 '11 at 07:59
  • It's not as easy as that. There's no reason a new file can't be created by a GUI program. The likely explanation is that your program has a bug in it, and after the bug has happened other things stop working. The bug is somewhere in the code you haven't posted. Good luck in finding it. – john Aug 21 '11 at 10:15
0

OK I found the solution. The only problem is that if you don't type in the whole path in the program, the file doesn't get opened. I replaced

FILE *f = fopen("trystl.geo","w");

with

FILE *f = fopen("c:/Users/anypath/trystl.geo","w");

it works!

Thank you for all your help!

Emre Turkoz
  • 868
  • 1
  • 23
  • 33
  • Probably it's because of what I wrote before: "this can happen if the current directory of your executable is not writable by an executable with "normal" privileges" – Matteo Italia Aug 21 '11 at 23:01
  • 3
    @Matteo Italia That doesn't make any sense. If the executable can't access the file with a relative filepath it won't be able to do it using an absolute path. The most likely reason is just that Emre assumes that the working dir is somewhere else than it actually is.. – Voo Aug 22 '11 at 00:51
  • 1
    @Voo: that's exactly what I am saying... <_ – Matteo Italia Aug 22 '11 at 08:30