I'm using clang/llvm to programmatically compile and link bits of C source. I'm finding that the llvm Linker doesn't seem to report the fact that unresolved externals exist in a module as an error.
I've the following code (forgive the length, but this really is the minimum required):
int CompileAndLink()
{
llvm::InitializeNativeTarget();
std::string code = "int UnresolvedFunction();\n"
"int main() { return UnresolvedFunction(); }";
clang::DiagnosticOptions diagnosticOptions;
clang::TextDiagnosticPrinter tdp( llvm::outs(), diagnosticOptions );
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs( new clang::DiagnosticIDs );
clang::Diagnostic diag( diagIDs, &tdp, false );
clang::FileSystemOptions fsOptions;
clang::FileManager fm( fsOptions );
clang::SourceManager sm( diag, fm );
clang::HeaderSearch hs( fm );
clang::TargetOptions targetOptions;
targetOptions.Triple = llvm::sys::getHostTriple();
clang::TargetInfo* ti = clang::TargetInfo::CreateTargetInfo( diag, targetOptions );
clang::HeaderSearchOptions headerSearchOptions;
clang::LangOptions langOptions;
clang::ApplyHeaderSearchOptions( hs, headerSearchOptions, langOptions, ti->getTriple() );
clang::PreprocessorOptions ppo;
clang::Preprocessor pp( diag, langOptions, *ti, sm, hs );
clang::FrontendOptions frontendOptions;
clang::InitializePreprocessor( pp, ppo, headerSearchOptions, frontendOptions );
pp.getBuiltinInfo().InitializeBuiltins( pp.getIdentifierTable(), langOptions );
llvm::MemoryBuffer* sourceBuffer = llvm::MemoryBuffer::getMemBufferCopy( code );
sm.createMainFileIDForMemBuffer( sourceBuffer );
clang::Builtin::Context bic( *ti );
clang::ASTContext astc( langOptions, sm, *ti,
pp.getIdentifierTable(),
pp.getSelectorTable(),
bic,
0 );
llvm::LLVMContext lc;
clang::CodeGenOptions codeGenOptions;
llvm::OwningPtr<clang::CodeGenerator> cg;
cg.reset( clang::CreateLLVMCodeGen( diag, "clang_test", codeGenOptions, lc ) );
if( cg == NULL ) {
printf( "could not create CodeGenerator\n" );
return -1;
}
clang::ParseAST( pp, cg.get(), astc );
if( tdp.getNumErrors() ) {
printf( "error parsing AST\n" );
return -2;
}
llvm::Module* new_module = cg->ReleaseModule();
if( !new_module ) {
printf( "error generating code\n" );
return -2;
}
llvm::Linker linker( "clang_test", "clang_test", lc, llvm::Linker::Verbose );
std::string error;
if( linker.LinkInModule( new_module, &error ) || !error.empty() ) {
printf( "link error\n" );
return -3;
}
llvm::Module* composite_module = linker.getModule();
if( composite_module == NULL ) {
printf( "link error\n" );
return -3;
}
llvm::ExecutionEngine *pEngine = llvm::ExecutionEngine::create( composite_module,
false,
&error );
if( !error.empty() || pEngine == NULL ) {
printf( "error creating ExecutionEngine\n" );
return -4;
}
llvm::Function* f = composite_module->getFunction( "main" );
if( f == NULL ) {
printf( "couldn't find main function\n" );
return -5;
}
// This will abort with the message:
// LLVM ERROR: Program used external function 'UnresolvedFunction' which could not be resolved!
std::vector<llvm::GenericValue> params;
llvm::GenericValue result = pEngine->runFunction( f, params );
printf( "function main returned %llu\n", result.IntVal.getZExtValue() );
return 0;
}
No errors happen anywhere until we call runFunction near the end, which gives the error "LLVM ERROR: Program used external function 'UnresolvedFunction' which could not be resolved!" before aborting.
I kinda expected LinkInModule or getModule to fail with some error, but this isn't the case. My question is: is there some way to determine that a module has unresolved externals, so as not to crash and burn when trying to execute the code? I've been spelunking through the llvm source for quite a while, and so far can't find what I'm looking for.
I'm using llvm/clang 2.9 on Mac OS X (x86_64), if that matters.
Edit: I've found a private function called GetAllUndefinedSymbols in the llvm sources (llvm-2.9/lib/Linker/LinkArchives.cpp), which appears to do what I want. I guess I was hoping there was an actual API for this, something I missed?
IIRC, nobody has ever asked for such an API, so none exists. I'm not entirely sure what you would do with such an API, anyway... any non-trivial program will reference symbols not defined in any .bc file, like malloc.
If you really want to check, something like the following should work:
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
if (I->isDeclaration())
UndefGlobals.insert(&*I);
for (Module::global_iterator I = M->global_begin(),
E = M->global_end();
I != E; ++I)
if (I->isDeclaration())
UndefGlobals.insert(&*I);
LLVM linker is used to link the Modules. Given that it's perfectly valid for Module to have the external declarations no errors should be given. So it's up to you to decide whether you need to error in such situation (some externals e.g. to C library functions in some situtation might be automagically resolved by JIT)
So, servn's code is what you have to do here.
Related
I just write a small MemoryHook library with c++ and use as preload.But when I run the test every time,there is a large amount of memory allocated,the size is 72704.
The usage is like this:
LD_PRELOAD=./libPreload.so ./XXX
I try to find all related library in ldd list, but no size is 72704.I removed other information and only kept the size, but also has this problem.
My initialize code:
static void TraceInitialize()
{
#ifdef _DEBUG
fprintf( stderr, "call TraceInitialize\n" );
#endif
pthread_mutex_lock( &s_mutexInit );
if ( s_status == TS_INITIALIZED ) { pthread_mutex_unlock( &s_mutexInit ); return; }
s_status = TS_INITIALIZING;
MemoryManager::initialize();
s_pRealMalloc = (FUNC_MALLOC)dlsym(RTLD_NEXT, "malloc");
s_pRealCalloc = (FUNC_CALLOC)dlsym(RTLD_NEXT, "calloc");
s_pRealRealloc = (FUNC_REALLOC)dlsym(RTLD_NEXT, "realloc");
s_pRealMemalign = (FUNC_MEMALIGN)dlsym(RTLD_NEXT, "memalign");
s_pRealValloc = (FUNC_VALLOC)dlsym(RTLD_NEXT, "valloc");
s_pRealFree = (FUNC_FREE)dlsym(RTLD_NEXT, "free");
assert( !( NULL == s_pRealMalloc || NULL == s_pRealCalloc || NULL == s_pRealRealloc ||
NULL == s_pRealMemalign || NULL == s_pRealValloc || NULL == s_pRealFree ) );
s_status = TS_INITIALIZED;
// printMap();
pthread_mutex_unlock( &s_mutexInit );
}
and trace malloc call:
static int s_no_hook = 0;
void* TraceMalloc( size_t size )
{
if ( s_status == TS_INITIALIZING ) return mockMemory::_mockMalloc( size );
if ( s_status != TS_INITIALIZED ) TraceInitialize();
void* p = _impMalloc( size, __sync_fetch_and_add( &s_no_hook, 1 ) );
__sync_fetch_and_sub( &s_no_hook, 1 );
return p;
}
When I test a demo problem just has empty main function.I expect not memory unfree but the real output is:
++++++++++++++ unfreed addr: 0x55cc4ae22260, size: 72704, serial: 1 ++++++++++++++
backtrace:
./libPreLoad.so(_ZN11MemoryTrace13MemoryManager14storeBacktraceEPNS0_11tagUnitNodeE+0x28)[0x7f62fd6cceba]
./libPreLoad.so(_ZN11MemoryTrace13MemoryManager10appendUnitEPvmb+0x9f)[0x7f62fd6ccbb7]
./libPreLoad.so(_ZN11MemoryTrace10_impMallocEmb+0x52)[0x7f62fd6cd4cb]
./libPreLoad.so(_ZN11MemoryTrace11TraceMallocEm+0x58)[0x7f62fd6cd286]
./libPreLoad.so(malloc+0x18)[0x7f62fd6cc812]
/usr/lib/x86_64-linux-gnu/libstdc++.so.6(+0x8f416)[0x7f62fd1cd416]
/lib64/ld-linux-x86-64.so.2(+0x10733)[0x7f62fd9e0733]
/lib64/ld-linux-x86-64.so.2(+0x10ca)[0x7f62fd9d10ca]
++++++++++++++ end ++++++++++++++
With no backtrace, the output is:
++++++++++++++ unfreed addr: 0x55f799c8e260, size: 72704, serial: 0 ++++++++++++++
backtrace:
++++++++++++++ end ++++++++++++++
And there is an additional problem that cannot count the memory release of static global variables.I can't find a suitable time to do this,even with attribute ((destructor(101))).
The big allocation which you are seeing is the C++ STL. As asked here by rerumu and answered by Nikos C.
The heap usage comes from the C++ standard library. It allocates
memory for internal library use on startup. If you don't link against
it, there should be zero difference between the C and C++ version.
With GCC and Clang, you can compile the file with:
g++ -Wl,--as-needed main.cpp
This will instruct the linker to not link against unused libraries. In
your example code, the C++ library is not used, so it should not link
against the C++ standard library.
I am using pHash and that library uses libpng. I am having issues running my program because libpng fails loading a PNG file.
Version of libpng: 1.4.19
Platform: Windows 10
Environment: Visual Studio 2015
Trivial
Just if you came up with the following questions...
Is the path to image correct? Yes
Is the image a valid PNG file? Yes
Code details
Library pHash uses CImg, the version of CImg they are using is a bit old I think:
#define cimg_version 148 // In CImg.h
I have debugged the library and the problems occurs in CImg.h (contained in the pHash VC++ project):
CImg<T>& _load_png(std::FILE *const file, const char *const filename) {
if (!file && !filename)
throw CImgArgumentException(_cimg_instance
"load_png() : Specified filename is (null).",
cimg_instance);
// Open file and check for PNG validity
if (Buffer) strcat(Buffer, "Checking PNG availability\r\n");
const char *volatile nfilename = filename; // two 'volatile' here to remove a g++ warning due to 'setjmp'.
std::FILE *volatile nfile = file?file:cimg::fopen(nfilename,"rb");
unsigned char pngCheck[8] = { 0 };
cimg::fread(pngCheck,8,(std::FILE*)nfile);
if (png_sig_cmp(pngCheck,0,8)) {
if (!file) cimg::fclose(nfile);
throw CImgIOException(_cimg_instance
"load_png() : Invalid PNG file '%s'.",
cimg_instance,
nfilename?nfilename:"(FILE*)");
}
// Setup PNG structures for read
png_voidp user_error_ptr = 0;
png_error_ptr user_error_fn = 0, user_warning_fn = 0;
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,user_error_ptr,user_error_fn,user_warning_fn);
if (!png_ptr) { // <-- PROBLEM HERE
if (!file) cimg::fclose(nfile);
throw CImgIOException(_cimg_instance
"load_png() : Failed to initialize 'png_ptr' structure for file '%s'.",
cimg_instance,
nfilename?nfilename:"(FILE*)");
...
}
The snippet shows the first part of CImg<T>& _load_png(std::FILE *const file, const char *const filename) which is called by the CImg library used by pHash.
Runtime issue
The code compiles fine but I get this error at runtime which I can see in the debugger:
CImgIOException: Failed to initialize 'png_ptr'...
In the point indicated in the code. I don't know why, it fails loading the image. The failure occurs when calling png_create_read_struct in CImg.h. That code is a bit obscure as defined through preprocessor directives. It is not clear why it is failing.
Any ideas?
Either if you are including libpng yourself or if another library is including and using libpng there are a few things to be aware of.
Which ever version of Visual Studio you are using, the libpng (dll or lib) files must be built from the same version of Visual Studio that your solution is linking against.
The platform you are using 32bit or 64bit is of concern.
Project settings when building the png library must match the build types of your current project. (Code Generation -> Runtime Library) must match. Your character set should match as well.
It is a little to difficult to tell what exactly is causing the problem but these are a few things to have a look at.
One thing I would suggest is to go to the website that provides the newest version of libpng and download it. Set a folder on your computer and create "system environment variable through windows" to point to your library. Open the solution to this library in the current version of VS you are using, build it out for both a static lib and dynamic lib (two different solutions) and build them both out for 32 bit and 64 bit saving the generated files into separated folders. Then go into the other library that depends on this and try to switch the dlls or libs and link against the new ones if possible. Also the other 3rd party library you should try to open its solution in the same version of VS and try to do a clean build from there. Then make sure you link everything properly. You may have to also modify the props file.
EDIT
I am not familiar with pHash or CImg, but I am familiar with libpng.
Here is a function in one of my projects to load in a png into a texture structure. Now this is a part of a class object that relies on many other classes, but you should be able to see from this snippet that I am successfully using libpng.
// ----------------------------------------------------------------------------
// loadPng()
bool TextureFileReader::loadPng( Texture* pTexture ) {
struct PngFile {
FILE* fp;
png_struct* pStruct;
png_info* pInfo;
// --------------------------------------------------------------------
PngFile() :
fp( NULL ),
pStruct( NULL ),
pInfo( NULL )
{} // PngFile
// --------------------------------------------------------------------
~PngFile() {
if ( NULL != fp ) {
fclose( fp );
}
if ( NULL != pStruct ) {
if ( NULL != pInfo ) {
png_destroy_read_struct( &pStruct, &pInfo, NULL );
} else {
png_destroy_read_struct( &pStruct, NULL, NULL );
}
}
} // ~PngFile
} png;
// Error Message Handling
std::ostringstream strStream;
strStream << __FUNCTION__ << " ";
if ( fopen_s( &png.fp, m_strFilenameWithPath.c_str(), "rb" ) != 0 ) {
strStream << "can not open file for reading";
throwError( strStream );
}
// Test If File Is Actually A PNG Image
const int NUM_HEADER_BYTES = 8;
png_byte headerBytes[NUM_HEADER_BYTES];
// Read The File Header
if ( fread( headerBytes, 1, NUM_HEADER_BYTES, png.fp ) != NUM_HEADER_BYTES ) {
strStream << "error reading header";
return false;
}
// Test Header
if ( png_sig_cmp( headerBytes, 0, NUM_HEADER_BYTES ) != 0 ) {
return false; // Not A PNG FILE
}
// Init PNG Read Structure - Test PNG Version Compatibility
png.pStruct = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
if ( NULL == png.pStruct ) {
strStream << "can not create struct for PNG file";
throwError( strStream );
}
// Init PNG Info Structure - Allocate Memory For Image Info
png.pInfo = png_create_info_struct( png.pStruct );
if ( NULL == png.pInfo ) {
strStream << "can not create info for PNG file";
throwError( strStream );
}
// Prepare For Error Handling
if ( setjmp( png_jmpbuf( png.pStruct ) ) ) {
strStream << "can not init error handling for PNG file";
throwError( strStream );
}
// Tell libPng Where The File Data Is
png_init_io( png.pStruct, png.fp );
// Tell libPng That You Have Already Read The Header Bytes
png_set_sig_bytes( png.pStruct, NUM_HEADER_BYTES );
// Read Image Data From The File
png_read_png( png.pStruct, png.pInfo, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_GRAY_TO_RGB, NULL );
// Show Image Attributes
png_byte colorType = png_get_color_type( png.pStruct, png.pInfo );
switch( colorType ) {
case PNG_COLOR_TYPE_RGB:
case PNG_COLOR_TYPE_RGBA: {
break;
}
default: {
strStream << "PNG is saved in an unsupported color type (" << colorType << ")";
throwError( strStream );
}
}
unsigned uHeight = png_get_image_height( png.pStruct, png.pInfo );
unsigned uBytesPerRow = png_get_rowbytes( png.pStruct, png.pInfo );
if ( 0 == uHeight || 0 == uBytesPerRow ) {
strStream << "invalid image size. Height(" << uHeight << "), Bytes per row(" << uBytesPerRow << ")";
throwError( strStream );
}
// Make Room For All Pixel Data
unsigned uTotalNumBytes = uHeight * uBytesPerRow;
pTexture->vPixelData.resize( uTotalNumBytes );
// Get All Pixel Data From PNG Image
png_bytepp ppPixelRow = png_get_rows( png.pStruct, png.pInfo );
for ( unsigned int r = 0; r < uHeight; ++r ) {
memcpy( &pTexture->vPixelData[ uBytesPerRow * ( uHeight - 1 - r ) ], ppPixelRow[r], uBytesPerRow );
}
// Store Other Values In Texture
pTexture->uWidth = png_get_image_width( png.pStruct, png.pInfo );
pTexture->uHeight = uHeight;
pTexture->hasAlphaChannel = ( colorType == PNG_COLOR_TYPE_RGBA );
return true;
} // loadPng
Looking through the source code for png_create_read_struct_2(), there are only 2 failure modes: inability to allocate memory, which is unlikely to be the problem, and a library version conflict.
If you are using a precompiled build of the pHash library, you must ensure that the copy of the libpng DLL that gets linked dynamically at runtime is the same version of the library that pHash was compiled against. The latest Windows build on pHash.org ships with libpng12.dll in the "Release" subdirectory, which is probably incompatible the version that you mentioned in the question, namely 1.4.19.
If you are building pHash from source, make sure that the libpng include files that are being used in your build process match the version being loaded at runtime.
If you're unsure exactly which DLLs are being loaded at runtime, the surest way I know to determine it would be to use Process Monitor.
I would like to load image to my application, but I have an error:
http://img510.imageshack.us/img510/5814/blad07864.png
This is a code of this application:
#include <stdio.h>
#include <stdlib.h>
#undef _UNICODE
#include "il.h"
#pragma comment( lib, "DevIL.lib" )
// Wow. DevIL is amazing.
// From http://gpwiki.org/index.php/DevIL:Tutorials:Basics
// The library consists of three sub-libraries:
// * IL - main DevIL library. It allows you to load and save images to files. Every function in this library have 'il' prefixed to their name.
// * ILU - this library contains functions for altering images. Every function in this library have 'ilu' prefixed to their name.
// * ILUT - this library connects DevIL with OpenGL. Every function in this library have 'ilut' prefixed to their name.
int main()
{
ilInit();
printf("DevIL has been initialized\n");
// Loading an image
ILboolean result = ilLoadImage( "tex1.png" ) ;
if( result == true )
{
printf("the image loaded successfully\n");
}
else
{
printf("The image failed to load\n" ) ;
ILenum err = ilGetError() ;
printf( "the error %d\n", err );
printf( "string is %s\n", ilGetString( err ) );
}
int size = ilGetInteger( IL_IMAGE_SIZE_OF_DATA ) ;
printf("Data size: %d\n", size );
ILubyte * bytes = ilGetData() ;
for( int i = 0 ; i < size; i++ )
{
// see we should see the byte data of the image now.
printf( "%d\n", bytes[ i ] );
}
}
I found code from this site: http://bobobobo.wordpress.com/2009/03/02/how-to-load-a-png-image-in-c/
Can you help me?
According to this post, 1290 means the image path wasn't found. Try using an absolute file path and see if it can load then.
I have an interesting problem that seems to be unresolved by my research on the internet.
I'm trying to load libraries dynamically in my c++ project with the functions from dlfcn.h. The problem is that when I try to reload the plugins at running time (because I made a change on any of them), the main program crashes (Segmentation fault (core dumped)) when dlclose() is called.
Here is my example that reproduces the error:
main.cpp:
#include <iostream>
#include <dlfcn.h>
#include <time.h>
#include "IPlugin.h"
int main( )
{
void * lib_handle;
char * error;
while( true )
{
std::cout << "Updating the .so" << std::endl;
lib_handle = dlopen( "./test1.so", RTLD_LAZY );
if ( ! lib_handle )
{
std::cerr << dlerror( ) << std::endl;
return 1;
}
create_t fn_create = ( create_t ) dlsym( lib_handle, "create" );
if ( ( error = dlerror( ) ) != NULL )
{
std::cerr << error << std::endl;
return 1;
}
IPlugin * ik = fn_create( );
ik->exec( );
destroy_t fn_destroy = ( destroy_t ) dlsym( lib_handle, "destroy" );
fn_destroy( ik );
std::cout << "Waiting 5 seconds before unloading..." << std::endl;
sleep( 5 );
dlclose( lib_handle );
}
return 0;
}
IPlugin.h:
class IPlugin
{
public:
IPlugin( ) { }
virtual ~IPlugin( ) { }
virtual void exec( ) = 0;
};
typedef IPlugin * ( * create_t )( );
typedef void ( * destroy_t )( IPlugin * );
Test1.h:
#include <iostream>
#include "IPlugin.h"
class Test1 : public IPlugin
{
public:
Test1( );
virtual ~Test1( );
void exec( );
};
Test1.cpp:
#include "Test1.h"
Test1::Test1( ) { }
Test1::~Test1( ) { }
void Test1::exec( )
{
std::cout << "void Test1::exec( )" << std::endl;
}
extern "C"
IPlugin * create( )
{
return new Test1( );
}
extern "C"
void destroy( IPlugin * plugin )
{
if( plugin != NULL )
{
delete plugin;
}
}
To compile:
g++ main.cpp -o main -ldl
g++ -shared -fPIC Test1.cpp -o plugin/test1.so
The problem occurs when for example I change something on the Test1::exec method (changing the string to be printed or commenting the line) and while the main program sleeps I copy the new test1.so to main running directory (cp). If I use the move command (mv), no error occurs. What makes the difference between using cp or mv? Is there any way to solve this problem or to do that using cp?
I'm using Fedora 14 with g++ (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4).
Thanks in advance.
The difference between cp and mv that is pertinent to this question is as follows:
cp opens the destination file and writes the new contents into it. It therefore replaces the old contents with the new contents.
mv doesn't touch the contents of the original file. Instead, it makes the directory entry point to the new file.
This turns out to be important. While the application is running, the OS keeps open handles to the executable and the shared objects. When it needs to consult one of the these files, it uses the relevant handle to access the file's contents.
If you've used cp, the contents has now been corrupted, so anything can happen (a segfault is a pretty likely outcome).
If you've used mv, the open file handle still refers to the original file, which continues to exist on disk even though there's no longer a directory entry for it.
If you've used mv to replace the shared object, you should be able to dlclose the old one and dlopen the new one. However, this is not something that I've done or would recommend.
Try this:
extern "C"
void destroy( IPlugin * plugin )
{
if( plugin != NULL && dynamic_cast<Test1*>(plugin))
{
delete static_cast<Test1*>(plugin);
}
}
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.
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.
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!