Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28808 Discussions

Calling WriteConsoleOutputAttribute function triggers access violation

TiborKibedi1
Beginner
2,214 Views

I try to recompile a project worked well under IFORT with the new IFX compiler. Calling the WriteConsoleOutputAttribute trigers an access violation. The function call is:

SCR_OutAtt = WriteConsoleOutputAttribute(SCR%OutputHandle, Loc(lpAttribute), nLength, dwWriteCoord, lpNumberOfCharsWritten)

 

Here are the parameters:

  Name Value Type

 scr%OutputHandle104INTEGER(8)
 lpAttribute7INTEGER(8)
 nlength47INTEGER(4)
dwWriteCoord{...}TYPE(TKLIBMOD::T_COORD)
 dwWriteCoord%X1INTEGER(2)
 dwWriteCoord%Y1INTEGER(2)
 lpNumberOfCharsWritten0INTEGER(8)

 

What is wrong? According to KERNEL32.f90 the parameter declarations are correct.

0 Kudos
1 Solution
Barbara_P_Intel
Employee
1,864 Views

@TiborKibedi1, with your scaled down reproducer, TkLib_Test.f90, I get an access violation like you do when compiling with ifx 2024.0.0.

BUT there's good news! With ifx 2024.1.0, it runs successfully, assuming this is the output you expect:

Q:\06175490>TkLib_Test.exe
 * * * TkLibTest * * *

Look for this new compiler in the next week or so.

 

 

View solution in original post

14 Replies
Steve_Lionel
Honored Contributor III
2,185 Views

Please attach a minimal but complete example source.

0 Kudos
TiborKibedi1
Beginner
2,156 Views

Thanks Steve for looking into this. I made a fresh installation of VS, One-Api and the Intel Compiler, but the problem still persists.

 

Attached is the source and project files. It was compiled and linked using MS VS 2022 17.9.4, One-API and IFX 2024.0.

The access violation happens at line 450 in  TK_LibMod.f90.

0 Kudos
andrew_4619
Honored Contributor III
2,152 Views

Well I think you mean this line:

SCR_OutAtt = WriteConsoleOutputAttribute(SCR%OutputHandle, Loc(lpAttribute), nLength, dwWriteCoord, lpNumberOfCharsWritten)

 

The last parameter _Out_       LPDWORD lpNumberOfAttrsWritten is meant to be an integer pointer to a dword so if you have:

integer(dword) :: Numbeofchars

you need to pass loc(Numbeofchars) and the function will write to that address. Dword is 4 bytes but the address is 8 bytes whicg is probs where it violates.

0 Kudos
TiborKibedi1
Beginner
2,102 Views

I am still having problems calling the WriteConsoleOutputAttribute(SCR%OutputHandle, Loc(SCR%Attributes), nLength, dwWriteCoord, Loc(NumberOfChars)) function. I followed the interface declaration in the KERNEL32.f90 module:

INTERFACE
FUNCTION WriteConsoleOutputAttribute( &
hConsoleOutput, &
lpAttribute, &
nLength, &
dwWriteCoord, &
lpNumberOfAttrsWritten)
import
integer(BOOL) :: WriteConsoleOutputAttribute ! BOOL
!DEC$ ATTRIBUTES DEFAULT, STDCALL, DECORATE, ALIAS:'WriteConsoleOutputAttribute' :: WriteConsoleOutputAttribute
integer(HANDLE) hConsoleOutput ! HANDLE hConsoleOutput
integer(LPWORD) lpAttribute ! WORD* lpAttribute
integer(DWORD) nLength ! DWORD nLength
TYPE (T_COORD) dwWriteCoord ! COORD dwWriteCoord
integer(LPDWORD) lpNumberOfAttrsWritten ! LPDWORD lpNumberOfAttrsWritten
END FUNCTION
END INTERFACE

 

The variables in my code are declared as

Integer(HANDLE)     SCR%OutputHandle

Integer(LPWORD)  SCR%Attributes

Integer(DWORD)    nLength

Type (T_COORD)   dwWriteCoord

Integer(LPDWORD)  NumberOfChars

 

Declaring "NumberOfChars" as DWORD makes no difference. The same code, initially developed and worked under previous versions of Intel Fortran and the problem surface with the latest  version, when the IFX compiler is being used. Interestingly, switching to IFORT in the latest distribution, the code works.

 

It may indicate a bug in the IFX compiler. Attached is a cut down version of the code.

 

I am using Win11, VS 2022, Intel oneAPI 2024.0, Intel Fortran Compiler 2024.0

0 Kudos
Steve_Lionel
Honored Contributor III
2,092 Views

Indeed, ifx does have a bug, but it is subtle.

The problem relates to the fourth argument, which is a structure of type T_COORD passed by value. T_COORD has two components that are 16-bit integers, so a single value of type T_COORD is 32 bits. The Windows API expects to receive this by-value, with the 32 bits passed in register R9; ifort does this, However, ifx doesn't want to pass this by value and instead passes something else, which causes it to try to write to improper locations in the console buffer.

I wrote a small test program to demonstrate this, but first wanted to see if using BIND(C) and VALUE rather than ATTRIBUTES STDCALL showed the same bug - it did not.

Here's the minimal example (sources attached). Just to make sure there was no issue with inlining, I put the subroutine in a separate source. I also have some evidence that ifx improperly receives a 32-bit structure when STDCALL is in effect.

struct.f90

module ctypes
use, intrinsic :: ISO_FORTRAN_ENV
type COORD_T
  integer(INT16) :: X, Y
  end type COORD_T
end module ctypes
program struct_test
use ctypes
implicit none
type(COORD_T) :: COORD
interface
  subroutine sub (COORD)
  import
!DIR$ ATTRIBUTES STDCALL :: sub
  type(COORD_T), VALUE :: COORD
  end subroutine sub
end interface
COORD = COORD_T (314,159)

call sub (COORD)
end

sub.f90

subroutine sub (A,B,C,COORD) BIND(C)
use ctypes
implicit none
integer, value :: A,B,C
type(COORD_T), value :: COORD
print '(2I6)', COORD
end subroutine sub
D:\Projects>ifort /c /Qdiag-disable:10448 sub.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.11.1 Build 20231117_000000
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.


D:\Projects>ifort /Qdiag-disable:10448 struct.f90 sub.obj
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.11.1 Build 20231117_000000
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 14.39.33522.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:struct.exe
-subsystem:console
struct.obj
sub.obj

D:\Projects>struct.exe
   314   159

D:\Projects>ifx -c sub.f90
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2024.0.2 Build 20231213
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.


D:\Projects>ifx struct.f90 sub.obj
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2024.0.2 Build 20231213
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

Microsoft (R) Incremental Linker Version 14.39.33522.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:struct.exe
-subsystem:console
struct.obj
sub.obj

D:\Projects>struct.exe
   314     0

The only solution for now is to keep using ifort.

 

0 Kudos
andrew_4619
Honored Contributor III
1,980 Views

There are some issues with the example shown above.  The interface for sub does not have BIND(C) specified and the arguments do not match the implementation (A,B,C??). If I also add BIND(C) to the type definition and remove A,B,C from sub it runs and  gives the correct answer.  

0 Kudos
Steve_Lionel
Honored Contributor III
2,085 Views

I do think you have a bug in your code, however. From what I'm reading, the routine expects to read nLength attributes, but your data structure has only one, so it will write random data to the other positions' attributes.

I did think of a workaround, which is to declare your own interface to WriteConsoleOutputAttribute that uses BIND(C) and VALUE instead of STDCALL - obviously this would be for x64 only. I have not tested this but I think it would work. But I still think it's better to keep using ifort for now.

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,998 Views

Steve,

Then would you/we assume that any user defined type that has sizeof of 1, 2, 4, 8 bytes (same sizeof as native types), passed by value to bind(C) procedure, would experience the problem with ifx (as of 3/25/24 or earlier release)?

 

If so, I can see a lot of code breaking. I am surprised this issue hasn't shown up much on this forum.

 

Jim

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,953 Views

The example was contrived to demonstrate the problem. Removing A, B and C hides the issue. 

Yes, anything up to 8 bytes should be passed by value when the STDCALL convention is in effect. I believe MSVC does this even for the C convention. I have not looked to see what convention is used on Linux. ifort does it right, ifx does not.

0 Kudos
Barbara_P_Intel
Employee
1,901 Views

@Steve_Lionel, I'm having trouble getting the same answers as you do with your reproducer using ifort.

Q:\tmp>ifort /Qdiag-disable:10448 -what struct.f90 sub.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.11.0 Build 20231010_000000
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.

 Intel(R) Fortran 2021.11.0-1242.01
 Intel(R) Fortran 2021.11.0-1242.01
Microsoft (R) Incremental Linker Version 14.38.33130.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:struct.exe
-subsystem:console
struct.obj
sub.obj

Q:\tmp>struct.exe
   256     0

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,898 Views

@Barbara_P_Intel Don't compile them together - do it separately as I did. However, I find the result you did get to be wrong as well - I can't reproduce that.

 

D:\Projects>ifort /Qdiag-disable:10448 -what struct.f90 sub.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.11.1 Build 20231117_000000
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.

 Intel(R) Fortran 2021.11.1-1242.01
 Intel(R) Fortran 2021.11.1-1242.01
Microsoft (R) Incremental Linker Version 14.39.33522.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:struct.exe
-subsystem:console
struct.obj
sub.obj

D:\Projects>struct.exe
   314   159
D:\Projects>ifx -c -what sub.f90
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2024.0.2 Build 20231213
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

 Intel(R) Fortran 24.0-1238.2

D:\Projects>ifx -what struct.f90 sub.obj
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2024.0.2 Build 20231213
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

 Intel(R) Fortran 24.0-1238.2
Microsoft (R) Incremental Linker Version 14.39.33522.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:struct.exe
-subsystem:console
struct.obj
sub.obj

D:\Projects>struct.exe
   314     0

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,890 Views

I just realized that I posted the wrong version of the source. The module ctypes should be in sub.f90, not struct.f90! Sorry for the confusion.

sub.f90

module ctypes
use, intrinsic :: ISO_FORTRAN_ENV
type COORD_T
  integer(INT16) :: X, Y
  end type COORD_T
end module ctypes
subroutine sub (A,B,C,COORD) BIND(C)
use ctypes
implicit none
integer, value :: A,B,C
type(COORD_T), value :: COORD
print '(2I6)', COORD
end subroutine sub

 struct.f90

program struct_test
use ctypes
implicit none
type(COORD_T) :: COORD
interface
  subroutine sub (A,B,C,COORD)
  import
!DIR$ ATTRIBUTES STDCALL :: sub
  integer :: A,B,C
  type(COORD_T):: COORD
  end subroutine sub
end interface
COORD = COORD_T (314,159)

call sub (1,2,3,COORD)
end
Barbara_P_Intel
Employee
1,877 Views

Thanks, @Steve_Lionel, for the update to your reproducer. ifx outputs the same wrong answers for me now with the latest release, 2024.0.0.

The better news is that with a preview of 2024.1.0 ifx prints the same right answers as ifort.

Look for that release in the next week or so.



Barbara_P_Intel
Employee
1,865 Views

@TiborKibedi1, with your scaled down reproducer, TkLib_Test.f90, I get an access violation like you do when compiling with ifx 2024.0.0.

BUT there's good news! With ifx 2024.1.0, it runs successfully, assuming this is the output you expect:

Q:\06175490>TkLib_Test.exe
 * * * TkLibTest * * *

Look for this new compiler in the next week or so.

 

 

Reply