PDA

View Full Version : QString -> C string -> Fortran subroutine



gib
9th October 2020, 14:45
I have a strange problem that may be created by my lack of C/C++ skills.

Starting from QStrings, I create two C strings that are passed to a Fortran subroutine. On my Windows 7 machine this works fine - almost all the time. But on a colleagues Windows 10 machine the strings are corrupted every time.

Here is the declaration of the Fortran subroutine in a DLL:

void execute(int *,char *, int *,char *, int *, int *);

Here is the summary of what I'm doing in the Qt code:

QString qsrt1, qstr2;
char *cstr1, *cstr2;
...
QByteArray ba = qstr1.toLocal8Bit();
cstr1 = ba.data();
ba = qstr2.toLocal8Bit();
cstr2 = ba.data();
...
execute(&ncpu,str1,&len1,str2,&len2,&res);

The Fortran code is correct, but on one machine the strings str1 and str2 appear as non-printing characters - random memory, I suspect.
What makes it very hard to debug is the fact that I almost never see the problem on my old W7 system; I thought it never happened, but then after running the program more than 20 times I got the corrupted string error. There is always the possibility that the problem is elsewhere in the Qt code, but I want to check that I'm not making a mistake with the string conversion. One question is whether I should be using const char * rather than char *.

Thanks.

d_stranz
9th October 2020, 19:18
Your colleague's Windows 10 machine is probably using unicode strings, which are usually multi-byte character strings. If the input strings are actually just normal 8-bit ASCII represented as two-byte unicode, you should be able to extract every other byte into a C-style string. Try converting your QString to a QLatin1String instead of local 8 bit.

Lesiok
10th October 2020, 08:19
From QByteArray::data() doc : The pointer remains valid as long as the byte array isn't reallocated or destroyed.
Look at example from this method doc.

d_stranz
10th October 2020, 18:51
The pointer remains valid as long as the byte array isn't reallocated or destroyed.

Ah, missed that in the code. Why would the behavior be different on Win 7?

ChrisW67
11th October 2020, 05:20
The OP's posted code does not pass the cstr1/cstr2 into the FORTRAN function anyway. As written it should not compile, so I guess the OP is actually passing the char pointers.

As for why it differs in Win 7 versus Win 10. Seems like luck that it works "most of the time" anywhere. For it to work, the second toLocal8Bit() call would have to cause the QByteArray to reallocate its internal buffer to hold the second string (e.g. the second string is longer), and the operating system would have to give it a distinct chunk of memory that was not simply an extension of the original buffer (i.e. not a realloc()), and the OS would have to not allocate the original buffer memory to anyone else or remove it from the process' memory space. Perhaps Win 10 has different memory allocation method or one that deliberately zeros/fills deallocated memory areas. Could also be the difference between a debug/release build or compiler/runtime optimizations for the target CPU.

gib
11th October 2020, 11:52
The OP's posted code does not pass the cstr1/cstr2 into the FORTRAN function anyway. As written it should not compile, so I guess the OP is actually passing the char pointers.

As for why it differs in Win 7 versus Win 10. Seems like luck that it works "most of the time" anywhere. For it to work, the second toLocal8Bit() call would have to cause the QByteArray to reallocate its internal buffer to hold the second string (e.g. the second string is longer), and the operating system would have to give it a distinct chunk of memory that was not simply an extension of the original buffer (i.e. not a realloc()), and the OS would have to not allocate the original buffer memory to anyone else or remove it from the process' memory space. Perhaps Win 10 has different memory allocation method or one that deliberately zeros/fills deallocated memory areas. Could also be the difference between a debug/release build or compiler/runtime optimizations for the target CPU.

Yes, sorry, the call should be:

execute(&ncpu,cstr1,&len1,cstr2,&len2,&res);

I don't use debug builds. Should I create another QByteArray?

QByteArray ba2 = qstr2.toLocal8Bit();
cstr2 = ba2.data();

ChristianEhrlicher
11th October 2020, 12:20
Should I create another QByteArray?

This is what the documentation and all here (and on forum.qt.io) tells you, yes.