- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In this program:
program Console1
use KERNEL32
implicit none
! Note space-terminated strings:
character*25 zinisection /'system_d '/
character*25 zkeywd /'systemtype '/
character*25 zkeywd_def /'unknown '/
character*25 zvalue
character*25 zinifile /'\\data\\pms.ini '/
integer*4 inumchar, isize
zvalue(1:)=' '
isize=25
inumchar=GetPrivateProfileString(
* zinisection,
* zkeywd,
* zkeywd_def,
* zvalue,
* isize,
* zinifile
* )
end program Console1
Compiled under 11.1 060 or 065, this windows call works with space-terminated strings. Under XE2011, it fails unless the strings are properly null-terminated. (BTW I tried all the calling conventions).
This is not great code, but there is a lot of it and it has worked for decades, including under Compaq and v11.1. If we have overlooked a switch or some magic that makes this work under XE2011, please advise.
program Console1
use KERNEL32
implicit none
! Note space-terminated strings:
character*25 zinisection /'system_d '/
character*25 zkeywd /'systemtype '/
character*25 zkeywd_def /'unknown '/
character*25 zvalue
character*25 zinifile /'\\data\\pms.ini '/
integer*4 inumchar, isize
zvalue(1:)=' '
isize=25
inumchar=GetPrivateProfileString(
* zinisection,
* zkeywd,
* zkeywd_def,
* zvalue,
* isize,
* zinifile
* )
end program Console1
Compiled under 11.1 060 or 065, this windows call works with space-terminated strings. Under XE2011, it fails unless the strings are properly null-terminated. (BTW I tried all the calling conventions).
This is not great code, but there is a lot of it and it has worked for decades, including under Compaq and v11.1. If we have overlooked a switch or some magic that makes this work under XE2011, please advise.
Link Copied
15 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You omit to say what 'fails' means.
Fails to link?
Fails with an execution error?
Fails by returning an unusual value for 'inumchar'?
Please expand.
Your snippet works in CVF returning, a value of '7' for inumchar.
Note that all your character strings will end with more than one blank character anyway as they are 25 characters long, longer than any string you define at the start.
Fails to link?
Fails with an execution error?
Fails by returning an unusual value for 'inumchar'?
Please expand.
Your snippet works in CVF returning, a value of '7' for inumchar.
Note that all your character strings will end with more than one blank character anyway as they are 25 characters long, longer than any string you define at the start.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for looking, I spent an hour wordsmithing that and yet did not mention that the code links and runs but does not retrieve the profilestring under XE2011, but does under CVF and v11.1. (Obviously, one needs to match the params to an actual INI file).
Obviously, it is not this single call that worries me, it is the apparently different string termination handling between compilers. Our system is large (compared to the staff, anyway) and string values enter from thousands of sources and result in thousands of calls in hundreds of modules.
Obviously, it is not this single call that worries me, it is the apparently different string termination handling between compilers. Our system is large (compared to the staff, anyway) and string values enter from thousands of sources and result in thousands of calls in hundreds of modules.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So, go back to good old 11.1 maybe?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The particular API requires null terminated strings. A space is not a "termination" character in Fortran or C. It likely only worked before because the C procedure found nulls by accident, likely following the string. The code is incorrect if it does not take explicit action to ensure a null character is present in the appropriate location within the allocated string buffer (not after it).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Getting XE2011 to work correctly by passsing null-terminated strings to GetPrivateProfileString turns out to be a bit of a problem, too. Here is a slightly altered version
[fortran] program Console1which, when used with this INI file
use KERNEL32
implicit none
character*25 zinisection /'Configuration'/
character*25 zkeywd /'Entry'/
character*25 zkeywd_def /'unknown'/
character*25 zvalue
character*25 zinifile /'langpms.ini'/
integer*4 inumchar, isize
zvalue(1:)=' '
isize=25
zinisection=TRIM(zinisection)//''C
zkeywd=TRIM(zkeywd)//''C
zvalue=TRIM(zvalue)//''C
zkeywd_def=TRIM(zkeywd)//''C
zinifile=TRIM(zinifile)//''C
inumchar=GetPrivateProfileString(
* zinisection,
* zkeywd,
* zkeywd_def,
* zvalue,
* isize,
* zinifile
* )
write(*,'(1x,I3,"|",A,"|")')inumchar,zvalue
end program Console1
[/fortran]
[bash][BEDW Ver 9.99, Mar 16 2012 15:34:12]gives, with IFORT 11.1.067 and XE2011 on XP-32:
Exec dir=C:editorsBEDW
Config dir=C:EDITORSBEDWCONFIG
Name=Norman Schwartzkopf
Initials=NS
Company=USArmy
Swap dir=s:Temp
[Configuration]
Entry=SeVeNs
[/bash]
[bash] 6|SeVeNs |
The null-termination has to be done properly, and it looks as if you will need to spend quite a bit of time if you have lots of strings in your code passed this way.
[/bash]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Does //'' really append a null character, I would think that was appending an empty string, ie. a no effect at all.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quite right, as I found on further checking. I remembered that sometime ago I used another compiler that use this funny way of adding a null -- in essense saying to itself, "this is so silly that he probably wants to do null termination". However, the present compiler does not. I have edited #5 to fix this.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think you meant to use //''C
The "C" is critical here.
The "C" is critical here.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I appreciate everyone's input here. The attraction of XE 2011 is the list file support. But this can wait.
I have read several Dr Fortran posts that the compiler is being gradually improved, and that blatantly nonconforming code will not be supported. I can't fault that. However, "proper" string termination for code that has worked for years is a tough sell to the boss right now. We will have to cross that bridge sooner or later, but not on this year's budget.
I have read several Dr Fortran posts that the compiler is being gradually improved, and that blatantly nonconforming code will not be supported. I can't fault that. However, "proper" string termination for code that has worked for years is a tough sell to the boss right now. We will have to cross that bridge sooner or later, but not on this year's budget.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you believe you have been null-terminating strings by appending '', then your code does not work - it just seems to - maybe - sometimes.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It also follows that, if "blank-terminated strings" have been "working", either the failures were infrequent enough to be noticed, or the consequences of wrong results returned by this particular API call are insignificant.
If either of these conditions is not true -- XE2011 showed that the first is not true any more--, the code needs to be fixed.
If either of these conditions is not true -- XE2011 showed that the first is not true any more--, the code needs to be fixed.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
String="abcdefg"c
is turned into a null-terminated (by adding CHAR(0)) string by the compiler during cmpilation.
It only does this because it recognises what comes before the 'C' as a character string.
You can turn
string1="abcdefg"
into a null terminated string by using
string2=trim(string1)//char(0)
provided that string1 is not already filled, otherwise the extra null character cannot be added to the end of it.
is turned into a null-terminated (by adding CHAR(0)) string by the compiler during cmpilation.
It only does this because it recognises what comes before the 'C' as a character string.
You can turn
string1="abcdefg"
into a null terminated string by using
string2=trim(string1)//char(0)
provided that string1 is not already filled, otherwise the extra null character cannot be added to the end of it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Once again I appreciate the help. The code is wrong, no doubt, but also the code worked thru 11.1, and the baseline is the result of scores of developers working over decades on a resulting product that is very large and complex compared to size of the support staff. That is the attraction and the burden of "legacy code". The suggestions are all great fixes - but we don't have the manpower to do what needs to be done right now.
So, for now, I just wanted to thank everyone and we are retiring this issue until we can afford to take it on.
So, for now, I just wanted to thank everyone and we are retiring this issue until we can afford to take it on.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can verify that character variables in 11.1 had a NUL character after the last character of the variable, but in 12.1 they are closely packed. I knew that we had traditionally put a NUL at the end of character literal constants but was unaware that the compiler did this for variables.
Of course, as noted in this thread, code that relied on the value of the character after the variable is just plain wrong, and we have historically not shied away from making changes that break incorrect programs, no matter how many years had gone by. I'm not sure what prompted this change and will ask the developers, but don't get your hopes up of the change being reversed.
Of course, as noted in this thread, code that relied on the value of the character after the variable is just plain wrong, and we have historically not shied away from making changes that break incorrect programs, no matter how many years had gone by. I'm not sure what prompted this change and will ask the developers, but don't get your hopes up of the change being reversed.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I determined that the difference was that 11.1 4-byte aligned the character variables, leaving zeroes typically in the unused bytes, and 12.0 packs the variables without padding. It's just like other uses of uninitialized data - anything that changes teh memory layout can reveal or hide an error.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page