Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix arrayWrite for arrays of strings #165

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

dirk-zimoch
Copy link
Contributor

@dirk-zimoch dirk-zimoch commented Sep 26, 2024

Writing arrays of strings (waveform or aao records with FTVL="STRING") wrote only the first element correctly and then just rubbish, possibly crashimg. The reason is that the code used a char** assuming a char*[num] array of pointers to strings but arrays of strings are actually char[num][len], i.e. one memory block with all the strings with a char* to the beginning.

@@ -1077,24 +1077,25 @@ DataElementUaSdk::writeArray (const char **value, const epicsUInt32 len,
char *val = nullptr;
const char *pval;
// add zero termination if necessary
if (memchr(value[i], '\0', len) == nullptr) {
if (memrchr(value, '\0', len) == nullptr) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of memrchr is more efficient than memchr because usually the last byte already matches 0. However not all Windows Versions seem to support it. I have no problem compiling it with VS 2019 but the CI fails.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memrchr is a GNU extension (https://www.gnu.org/software/libc/manual/html_node/Search-Functions.html). I am surprised that the MSVC build on your local system supports it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use memchr on Windows.
Could be a Win-only #define memrchr memchr, couldn't it?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Äh, memrchr() is not the same as memchr().
If you have trailing crap after a good string, then they may return differnent
values.
Unless someone measures the performance, and says it is 50% faster
using memrchr(), I would vote for using memchr():
a) it is more readable
b) modern processors/compilers do already optimize these mem() operations.
Or do I miss something ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found the reason why it did not trigger in my builds: I have no UaSDK for Windows, so I build the UaSDK Version only for Linux and the open62541 code does not need it.

About Efficiency: Probability that the first byte is 0 is close to 0 (only for empty strings). Probability that the last byte is 0 is 100% (I found no way to put an unterminated string into a string array.) Just to be on the save side, simply checking the last byte is sufficient. Any 0 byte before will be handled by strncpy correctly, even in the very unlikely case of "crap" in the last byte.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given how rare arrays of strings are in EPICS... the time savings could be up to milliseconds per year! (Across all EPICS-OPCUA users, of course.)

Copy link
Contributor Author

@dirk-zimoch dirk-zimoch Sep 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So rare that even the tests did not cover them ;-)

@dirk-zimoch dirk-zimoch force-pushed the fix_arrayWrite_strings branch from 726bfdf to 8ca3dc3 Compare September 27, 2024 09:07
@dirk-zimoch
Copy link
Contributor Author

The builds fail again with some "bad decrypt" exception. I am giving up on this stuff with "secrets" and will from now on ignore any CI failures in this project on my branches. @ralphlange, please check with your setup if it works.

@ralphlange
Copy link
Member

Thanks! The check looks much better now.
(And even more efficient!)

@ralphlange
Copy link
Member

ralphlange commented Sep 27, 2024

The builds fail again with some "bad decrypt" exception. I am giving up on this stuff with "secrets" and will from now on ignore any CI failures in this project on my branches. @ralphlange, please check with your setup if it works.

The situation is as before:
Your branch builds work. (As you have the secret.)
Pull requests builds don't work.

See https://github.com/dirk-zimoch/opcua/actions

I will check if I can selectively suppress PR builds of the UA SDK.

@dirk-zimoch
Copy link
Contributor Author

Ah, right. I saw the failure here and thought "not again". Everything looks ok here: https://github.com/dirk-zimoch/opcua/actions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants