Sunday, March 5, 2023

Digest for comp.lang.c++@googlegroups.com - 25 updates in 6 topics

Malcolm McLean <malcolm.arthur.mclean@gmail.com>: Mar 05 07:11AM -0800

On Saturday, 4 March 2023 at 22:55:37 UTC, Ben Bacarisse wrote:
> would be a Malcolm function, and you can't mean all the bits in the
> entire (virtual) system or the specification for such a function would
> be ridiculous.
 
A mathematical function doesn't cease to be a mathematical function
because its specification is ridiculous. If each possible bit state on code
entry maps to one and only one possible bit state on code exit, and
the code doesn't do anything else, like turn LEDs on or off, then the
code is a "function" or if you prefer, a "Malcolm function".
Tim Rentsch <tr.17687@z991.linuxsc.com>: Mar 05 08:13AM -0800

> intents and purposes, the term is identical in meaning to the term
> "function", used in the accepted sense in a computer context, not in
> the C sense to mean "subroutine".
 
This posting is not a response but a request for clarification.
Is this function
 
int
contents_of( int *p ){
return *p;
}
 
one you would call a Malcolm function?
Malcolm McLean <malcolm.arthur.mclean@gmail.com>: Mar 05 09:05AM -0800

On Sunday, 5 March 2023 at 16:14:15 UTC, Tim Rentsch wrote:
> return *p;
> }
 
> one you would call a Malcolm function?
 
Yes. On code entry, bits are pointed to by p. On code exit, the return
value contains the same bits. It's not a very useful function, but it's
clearly a function, in the mathematical sense of computing a mapping
of one bit state to another bit state, and doing nothing else.
You can argue that, on many architectures, if we pass it null, it will
put a message on the error output stream, and terminate the program.
A function can't do that. So it's not a function. But the answer is that
invalid values of p are not in its domain, and it's still a function.
 
I don't use the term "Malcolm function". They just functions (of bits).
The confusion is because C uses the term to mean "subroutine", and other
languages sometimes use the term syntactically, to mean code with a return
values that can be uses as the right hand side of an assignment. But
people have got the idea that the concept is my invention, whilst it isn't.
It's very well established terminology.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Mar 05 08:44PM

>> be ridiculous.
 
> A mathematical function doesn't cease to be a mathematical function
> because its specification is ridiculous.
 
Of course. And the same would be true of non-mathematical functions as
well. I'm trying to find out how your functions are specified. How is
the Malcolm function that "just returns 10" specified?
 
> possible bit state on code exit, and the code doesn't do anything
> else, like turn LEDs on or off, then the code is a "function" or if
> you prefer, a "Malcolm function".
 
So
 
int f(int x) { extern int inc; return x + inc++; }
 
is a Malcolm function, yes?
 
--
Ben.
Mr Flibble <flibble2@reddwarf.jmc.corp>: Mar 05 09:00PM

On 05/03/2023 20:44, Ben Bacarisse wrote:
 
> So
 
> int f(int x) { extern int inc; return x + inc++; }
 
> is a Malcolm function, yes?
 
Mathematical functions don't have side-effects; f has side effects so
isn't a mathematical function.
 
/Flibble
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Mar 05 01:59PM -0800

On 3/5/2023 1:00 PM, Mr Flibble wrote:
 
>> is a Malcolm function, yes?
 
> Mathematical functions don't have side-effects; f has side effects so
> isn't a mathematical function.
 
Imvvho, it is still "mathematical", in the sense that it performs
mathematical "tasks" on the mutable state? A side effect to me means the
function did something else besides providing a return value.
Malcolm McLean <malcolm.arthur.mclean@gmail.com>: Mar 05 02:26PM -0800

On Sunday, 5 March 2023 at 20:44:59 UTC, Ben Bacarisse wrote:
> Of course. And the same would be true of non-mathematical functions as
> well. I'm trying to find out how your functions are specified. How is
> the Malcolm function that "just returns 10" specified?
 
It's embedded in the code somewhere. So for each possible (legal) state
of the bit store on code entry there is one and one only state of the bit
store on code exit, and the code does not cause any actions over than
moving bits in the memory to be taken. So it's code that calculates a function,
or a "Malcolm function".
Of course you'd specify it as "returns 10". It's not particularly helpful to think
in terms of the whole bit store. It's only helpful if you want to draw a distinction
between code which calculates functions and code which performs actions,
and someone is a bit shaky on what a function is.
> So
 
> int f(int x) { extern int inc; return x + inc++; }
 
> is a Malcolm function, yes?
 
Exactly. With this one, we do have to a bit more careful. The bits that represent
inc are incremented, whilst a value based on that number and the argument goes
into the return value. Again, we can in principle specify it by brute force, by
enumerating every possible state of the bit store on code entry and code exit.
Which tells us that it is a "function", or if you want to be pedantic about it, "code
which calculates a function".
Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Mar 05 09:59AM -0800

Let's say I have one program and one shared library on a *nix computer.
 
I build my program to link dynamically with the library as follows:
 
g++ -o prog prog.cpp -l:libmonkey.so
 
So let's say that this produces an executable file that works fine.
 
Next I change the build command to the following:
 
g++ -o prog prog.cpp
 
And so now of course I get a linker error because of unresolved symbols (I'm missing the functions implemented in the library). To overcome this linker error, I change the build command again:
 
g++ -o prog prog.cpp -Wl,--unresolved-symbols=ignore-in-object-files
 
So now we get a viable executable file, but when we run it, it segfaults. It segfaults when it tries to access something from the shared library.
 
So next I make a one-line change at the beginning of 'main':
 
int main(void)
{
dlopen("libmonkey.so", RTLD_NOW|RTLD_GLOBAL);
 
// The rest of main goes here
}
 
So now the program works fine.
 
I think however, that this strategy only works when the program doesn't use global variables which are exported from the library. That is to say, it works fine for exported functions but not for exported global variables. Am I right here?
 
I have more testing to do on this, but I need to get this working. I need to remove the library from the 'NEEDED' section in the program's ELF file, and instead I have to use 'dlopen' at runtime to load it in.
 
How can I get this to work with the global variables also? I've tried declaring the global variable as a weak symbol in the program, and that seems to work, but I don't want to have to go looking for a list of all the global objects exported from the shared library.
 
Also I realise that things get complicated if there's a global object in the program whose constructor accesses the shared library (in which case I need to make use of __attribute__((constructor)). But I'll deal with thay conundrum later.
Christian Gollwitzer <auriocus@gmx.de>: Mar 05 07:12PM +0100

Am 05.03.23 um 18:59 schrieb Frederick Virchanza Gotham:
 
> So now the program works fine.
 
> I think however, that this strategy only works when the program doesn't use global variables which are exported from the library. That is to say, it works fine for exported functions but not for exported global variables. Am I right here?
 
> I have more testing to do on this, but I need to get this working. I need to remove the library from the 'NEEDED' section in the program's ELF file, and instead I have to use 'dlopen' at runtime to load it in.
 
 
As always, I'm questioning this NEED. Why do you want to load the
required library at runtime? Do you want to adjust the path at
initialization? If it is only about packaging the library with the
application, you could use the run-path when linking; e.g. say your
library is distributed in a lib folder alongside your executable, then
 
-Wl,-rpath,'$ORIGIN'/lib
 
in the linker line would do that. Another alternative is to write a
small shell script which adjusts LD_LIBRARY_PATH before invoking the binary.
 
I can see the need for dlopen() only in case where the functionality is
somewhat optional, like in a plugin system.
 
Christian
Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Mar 05 11:11AM -0800

> As always, I'm questioning this NEED.
 
 
I'm combining a console program and a GUI program into one program (i.e. one executable).
 
Depending upon the command-line arguments to the program, it might enter into GUI mode, and if it does, it needs to load the GUI libraries.
 
But if it runs in console mode, I don't want the system to need to have the Gui libraries installed.
Christian Gollwitzer <auriocus@gmx.de>: Mar 05 10:45PM +0100

Am 05.03.23 um 20:11 schrieb Frederick Virchanza Gotham:
 
> I'm combining a console program and a GUI program into one program (i.e. one executable).
 
> Depending upon the command-line arguments to the program, it might enter into GUI mode, and if it does, it needs to load the GUI libraries.
 
> But if it runs in console mode, I don't want the system to need to have the Gui libraries installed.
 
This usually works by exporting a known entry function from the library,
load the library by dlopen() and find the function using dlsym(). Put
all the functionality into the library, so that you can invoke the GUI
stuff with a simple call. It doesn't make sense to have global variables
in the main program have influenced by loadable library.
 
If you need a lot of the functionality of the main program in the
library, then instead put this functionality in a library if its own
(say, libengine.so). Then the main program reduces to
 
if (std::string(argv[1] == "-gui") {
dlopen();
run_gui = dlsym("...");
run_gui();
} else {
run_cmdline();
}
 
Link both this main and the GUI library with libengine.so.
 
Christian
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Mar 04 03:25PM -0800

On 3/3/2023 8:38 PM, Bonita Montero wrote:
 
>> Not until you model it in something like Relacy.
>> No time right now to  read all of your code and verify it.
 
> Sorry, the code is trivial from the MT-perspective.
 
I have seen too many bugs in code that others have labeled trivial
before... Btw, I am busy on another project. :^)
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Mar 04 03:26PM -0800

On 3/4/2023 11:07 AM, Bonita Montero wrote:
> ...
> string dequeued( stringQueue.dequeue() );
 
> That's all.
 
Take the time to model it in a race detector.
Bonita Montero <Bonita.Montero@gmail.com>: Mar 05 05:18AM +0100

Am 05.03.2023 um 00:26 schrieb Chris M. Thomasson:
 
> Take the time to model it in a race detector.
 
You are an idiot; no one needs a race-detector for such simple code.
Bonita Montero <Bonita.Montero@gmail.com>: Mar 05 05:19AM +0100

Am 05.03.2023 um 00:25 schrieb Chris M. Thomasson:
 
> I have seen too many bugs in code that others have labeled
> trivial before... Btw, I am busy on another project. :^)
 
Idiot. You didn't have a look at my code.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Mar 05 08:38AM -0800


>> Even better, that you updated to more modern software. :-o
 
> I believe the first time that I've taken issue with Tim Rentsch, but,
> yes :-)
 
Note that my comment is not about tools but about matters of
visual presentation. The tools I use have no problem dealing
with long lines but what tools do is not the high order bit here.
There are good human factors reasons to limit line length to
somewhere close to 80 characters, and that point is what I am
hoping to convey.
 
Note also that I am not the only newsgroup member, nor even the
first, to complain about Alf's idiosyncratic style choices.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Mar 05 08:43AM -0800


> On 2023-02-24 4:51 PM, Tim Rentsch wrote:
 
[...]
 
>> to 80 characters, as many coding standards and style guidelines
>> recommend.
 
> Even better, that you updated to more modern software. :-o
 
I'm sad to say that, coming from you, this statement doesn't
surprise me. AFAIAA more people complain about problems your
tools cause than there are for the tools used in my postings.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Mar 05 01:37PM -0800

On 3/4/2023 8:18 PM, Bonita Montero wrote:
> Am 05.03.2023 um 00:26 schrieb Chris M. Thomasson:
 
>> Take the time to model it in a race detector.
 
> You are an idiot; no one needs a race-detector for such simple code.
 
There is nothing wrong with using a race-detector. Model the simple code
in the detector, then move it into your C++ code. There is nothing wrong
with modeling a lock-based and/or lock-free, wait-free synchronization
scheme in a race detector, before, you flesh it out in real code.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Mar 05 01:41PM -0800

On 3/4/2023 8:19 PM, Bonita Montero wrote:
 
>> I have seen too many bugs in code that others have labeled
>> trivial  before... Btw, I am busy on another project. :^)
 
> Idiot. You didn't have a look at my code.
 
I did, but not long enough to verify it as 100% kosher.
Pawel Por <porparek@gmail.com>: Mar 05 03:34AM -0800

> What behavior made you to draw that conclusion ?
I cannot see any Dog's constructor or operator to be called while calling MyList::push_front(). No __PRETTY_FUNCTION__ output (refer to the code below).
 
> What are we expected to see in this output ?
I expect the Dog::operator=(Dog&&) to be called
 
I'm aware that __PRETTY_FUNCTION__ shows the following but why the Dog::operator=(Dog&&) isn't called ?
void MyList<T>::push_front(T&&) [with T = Dog]
 
The updated code is as follows (I'm using g++ 9.4.0 Ubuntu 20.04)
#include <iostream>
#include <forward_list>
#include <utility>
 
template <typename T>
void p(const T &v)
{
std::cout << v << std::endl;
}
 
struct Dog
{
Dog() { p(__PRETTY_FUNCTION__); }
Dog(const Dog&) { p(__PRETTY_FUNCTION__); }
Dog(Dog&&) { p(__PRETTY_FUNCTION__); }
 
Dog& operator=(const Dog&) { p(__PRETTY_FUNCTION__); return *this; }
Dog& operator=(Dog &&) { p(__PRETTY_FUNCTION__); return *this; }
};
 
template<typename T>
struct MyList
{
void push_front(T &&v) { p(__PRETTY_FUNCTION__); T x = std::move( v ); (void) x; }
};
 
int main()
{
MyList<Dog> ml;
std::forward_list<Dog> fl;
Dog dog;
 
p("ml.push_front");
ml.push_front(std::move(dog));
p("fl.push_front");
fl.push_front(std::move(dog));
}
Pawel Por <porparek@gmail.com>: Mar 05 10:20AM -0800

> > What are we expected to see in this output ?
> I expect the Dog::operator=(Dog&&) to be called
I expect the Dog::Dog(Dog&&) to be called (sorry for confusion)
Andrey Tarasevich <andreytarasevich@hotmail.com>: Mar 05 10:27AM -0800

On 03/05/23 3:34 AM, Pawel Por wrote:
>> What behavior made you to draw that conclusion ?
> I cannot see any Dog's constructor or operator to be called while calling MyList::push_front(). No __PRETTY_FUNCTION__ output (refer to the code below).
 
Um... What? But your code outputs
 
Dog::Dog(Dog&&)
 
from inside 'MyList::push_front()'. This is clearly a call to Dog's
constructor. Why do you say that you "cannot see any Dog's constructor
[...] to be called"?
 
And that still does not allow you to differentiate between lvalue
reference and rvalue reference. So, my question still stands.
 
>> What are we expected to see in this output ?
> I expect the Dog::operator=(Dog&&) to be called
 
Why? The code you provided does not use assignment operator at all. Why
would you expect assignment operator to be called?
 
> I'm aware that __PRETTY_FUNCTION__ shows the following but why the Dog::operator=(Dog&&) isn't called ?
 
Again, show me the exact location where you expect the assignment
operator to be called.
 
--
Best regards,
Andrey
Andrey Tarasevich <andreytarasevich@hotmail.com>: Mar 05 10:30AM -0800

On 03/05/23 10:20 AM, Pawel Por wrote:
>>> What are we expected to see in this output ?
>> I expect the Dog::operator=(Dog&&) to be called
> I expect the Dog::Dog(Dog&&) to be called (sorry for confusion)
 
But it _is_ called. Here's the output I get from your code
 
Dog::Dog()
ml.push_front
void MyList<T>::push_front(T&&) [with T = Dog]
Dog::Dog(Dog&&)
fl.push_front
Dog::Dog(Dog&&)
 
--
Best regards,
Andrey
Tim Rentsch <tr.17687@z991.linuxsc.com>: Mar 05 08:20AM -0800


> The problem isn't about alignment, but that the code uses a pointer to
> signed char. The standard allows inspecting bytes as unsigned char,
> but has no special allowance for signed char.
 
This comment is at best misleading. A static_cast to (unsigned char *)
isn't allowed any more than a static_cast to (int8_t *) is.
MarioCPPP <NoliMihiFrangereMentulam@libero.it>: Mar 05 05:14PM +0100

Could sb explain me what is the semantic meaning of that
syntax and what possible use-cases does a Type && have ?
 
A reference is an "hidden" immutable pointer to an object
(with some syntactic sugar to access members by DOT and not
by ->), which should also a be warranty to point to a valid
object (no nullptr).
 
But a Type && seems to be also able to point to ... to what ?
What is for ?
 
--
1) Resistere, resistere, resistere.
2) Se tutti pagano le tasse, le tasse le pagano tutti
MarioCPPP
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: