Re: Managing malloced memory

2021-10-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 10/11/21 6:53 AM, anon wrote:

On Thursday, 7 October 2021 at 11:55:35 UTC, Steven Schveighoffer wrote:
The GC is technically not required to free any blocks ever. But in 
general, it does.


When it does free a struct, as long as you allocated with `new`, it 
should call the dtor.


In practice when I played around with it, destructor always got called 
by GC. But: https://dlang.org/spec/class.html#destructors says at point 6:
The garbage collector is not guaranteed to run the destructor for all 
unreferenced objects.
Is it the same for structs or are these destructors guaranteed to be 
called? Would it be suitable to clean up tempfiles with GC-managed structs?


It's not guaranteed to run the destructor because it's not guaranteed to 
clean up the memory at all. For sure, it will not clean up the memory 
without first running the destructor (except on process termination, 
which will obviously clean up everything without running destructors).


This is par for the course with GCs, they all have fine print that says 
the destructors (finalizers) may not be called. Most of the time it 
means that the memory will not get cleaned up too. But it's technically 
spec-compliant for the GC to not run the dtor and clean up the memory.


Temp files I would say to ensure they are cleaned up synchronously. 
Though my best practice recommendation is to clean up non-memory 
resources using destructors that will leak if you forget to 
synchronously clean them up.


Just FYI, you should reply to the posts that you quote, or at least 
copy the "X Y wrote" line so people understand the thread.


Alright. If I want to reply to multiple people, should I post twice or 
quote both in the same post?


You can do it either way. It just looked from your message like I was 
saying the things that H.S. Teoh did.


For sure, if you want a response from someone, it's good to reply 
directly to their post.


The destructor is called once per copy. This is why disabling copy 
prevents double freeing.


There are cases where the compiler avoids calling the destructor 
because the instance is moved. Such as returning a newly constructed 
item (typically referred to as an "rvalue"), or passing a newly 
constructed item into a parameter. The parameter will be destroyed, 
but the call-site constructed item will not.




Is there any reference for exactly how these rules apply, or is this 
implementation defined? The 
[specification](https://dlang.org/spec/struct.html#struct-destructor) 
says that destructors are called when objects go out of scope. Your 
examples seem to suggest that this is untrue in some cases.


A struct on the heap doesn't go out of scope after the stack frame, 
since it's still on the heap.


Unfortunately, the spec is maintained over history, and historically, 
struct destructors were not run by the GC even when the memory was 
cleaned up. So this terminology is focused on structs that were mostly 
only functional on the stack.


-Steve


Re: Linker error

2021-10-11 Thread jfondren via Digitalmars-d-learn
On Monday, 11 October 2021 at 23:43:17 UTC, Ruby The Roobster 
wrote:

package mixin template move__() {
	pragma(inline) package void mv(Point moveby, ref Skeleton 
tomove)	{

foreach(i;tomove.faces) {
foreach(k;i.lines)  {
foreach(j;k.mid_points) {
j += moveby;
}
k.start += moveby;
k.stop += moveby;
}
i.center += moveby;
}
tomove.center += moveby;
}
}


It compiles if this `pragma(inline)` is removed.


Re: How to do a function pointer to "malloc" and "free"?

2021-10-11 Thread Steven Schveighoffer via Digitalmars-d-learn

On 10/10/21 6:44 AM, rempas wrote:

I'm having the following C code:

```
static void* (*ppmalloc)(size_t) = malloc;
static void (*ppfree)(void*) = free;
```

I want to covert this code in D so I try to do the following:

```
static void* function(size_t)*ppmalloc = malloc;
static void  function(void*)*ppfree = free;
```

If I do that, I'm getting the following error message:

```
Error: function `core.stdc.stdlib.malloc(ulong size)` is not callable 
using argument types `()`

```

I'm also trying to do the same using "pureMalloc" and "pureFree" instead 
but this time I'm getting the following error:


```
cannot implicitly convert expression `pureMalloc()(size_t size)` of type 
`void` to `extern (C) void* function(ulong)*`

```

Any ideas?


I know most of this is answered already, but I would suggest actually just:

```d
auto ppmalloc = 
```

which all of D's type inference to allow you to declare the appropriate 
function type.


BTW, you get the error because in D, empty parentheses are optional. So 
when you say `malloc`, it really means `malloc()`. Which is one big 
reason why the & operator is required.


-Steve


Linker error

2021-10-11 Thread Ruby The Roobster via Digitalmars-d-learn

So, I have the following two files:

skeleton.d:
```d
/*skeleton.d by Ruby The Roobster*/
/*Version 1.0 Release*/
/*Module for representing skeletons in the D Programming Language 
2.0*/
/*This program is free software: you can redistribute it and/or 
modify
it under the terms of the GNU General Public License as published 
by

the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see 
.*/

/** Copyright: 2021, Ruby The Roobster*/
/**Author: Ruby The Roobster, michaeleverest...@gmail.com*/
/**Date: October 1, 2021*/
/** License:  GPL-3.0*/
module dutils.skeleton;
/**Struct for representing a point.*/
public struct Point { //Point structure...
///Point.x is the 'x' coordinate of the point.
real x;
///Point.y is the 'y' coordinate of the point.
real y;
///Point.z is the 'z' coordinate of the point.
real z;
void opAssign(Point rhs){
this.x = rhs.x;
this.y = rhs.y;
this.z = rhs.z;
}
void opOpAssign(string op)(Point rhs)   {
mixin("this.x " ~ op ~ "= rhs.x;");
mixin("this.y " ~ op ~ "= rhs.y;");
mixin("this.z " ~ op ~ "= rhs.z;");
}
}
/**Struct for representing a face of a skeleton that is made out 
of lines.*/

public struct Face  { //Face(of a 3D shape) structure...
	///Face.lines is an array of all the lines that connect to form 
the face.

Line[] lines;
///Face.center is the center point of the face.
Point center;
void opAssign(Face rhs) {
this.lines.length = rhs.lines.length;
foreach(i;0 .. this.lines.length)   {
this.lines[i] = rhs.lines[i];
}
}
}
/**Struct for representing a 3D skeleton.*/
public struct Skeleton  { //Skeleton of a 3D structure...
	///Skeleton.faces is an array of the faces that make up the 
Skeleton.

Face[] faces;
///Skeleton.center is the center point of the skeleton.
Point center;
void opAssign(Skeleton rhs) {
this.faces.length = rhs.faces.length;
foreach(i;0 .. this.faces.length)   {
this.faces[i] = rhs.faces[i];
}
this.center = rhs.center;
}
}

/**Struct for representing a line composed of at least a starting 
point and an end point.

  *Notes:
  *This struct doesn't check to make sure that the line made is 
an actual line and assumes the user knows what they are doing.

*/
public struct Line  { //Line struct...
	///Line.mid_points is an array containing all of the points that 
are neither start nor end points.

Point[] mid_points;
///Line.start is the start point of the line.
Point start;
///Line.end is the end point of the line.
Point stop;
void opAssign(Line rhs) {
this.start = rhs.start;
this.stop = rhs.stop;
this.mid_points.length = rhs.mid_points.length;
foreach(i;0 .. this.mid_points.length)  {
this.mid_points[i] = rhs.mid_points[i];
}
}
}
```

physics.d:
```d
/*physics.d by Ruby The Roobster*/
/*Version 0.35 testing*/
/*Module for basic physics in the D Programming Language 2.0*/
/*This program is free software: you can redistribute it and/or 
modify
it under the terms of the GNU General Public License as published 
by

the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see 
.*/

/** Copyright: 2021, Ruby The Roobster*/
/**Author: Ruby The Roobster, michaeleverest...@gmail.com*/
/**Date: October 11, 2021*/
/** License: GPL-3.0*/
module dutils.physics;
public import dutils.skeleton;

package mixin template move__() {
	pragma(inline) package void mv(Point moveby, ref Skeleton 
tomove)	{

foreach(i;tomove.faces) {
foreach(k;i.lines)  {
foreach(j;k.mid_points) {
j += moveby;
}
k.start += 

Re: Windows printing

2021-10-11 Thread Imperatorn via Digitalmars-d-learn

On Monday, 11 October 2021 at 17:59:39 UTC, frame wrote:

On Thursday, 7 October 2021 at 18:00:17 UTC, Imperatorn wrote:


I think that might depend on OS version iirc.


Well, I guess you are right. If I just put the 
DocumentPropertiesA() call in a loop, it locks in immediately 
with 0 or between 60 - 400 failed attempts, depending on the 
printer driver.


Very weird behavior but It cannot caused by my program - the 
input data in memory is constant and not corrupted.


Also interesting the amount of failed attempts stays exactly 
the same or just moves a bit but is never really random.


Interesting. Have you tried any sanity checking using any other 
language or using some existing code?


Like, maybe you can use wmi for this? idk


Re: Windows printing

2021-10-11 Thread frame via Digitalmars-d-learn

On Thursday, 7 October 2021 at 18:00:17 UTC, Imperatorn wrote:


I think that might depend on OS version iirc.


Well, I guess you are right. If I just put the 
DocumentPropertiesA() call in a loop, it locks in immediately 
with 0 or between 60 - 400 failed attempts, depending on the 
printer driver.


Very weird behavior but It cannot caused by my program - the 
input data in memory is constant and not corrupted.


Also interesting the amount of failed attempts stays exactly the 
same or just moves a bit but is never really random.


Re: Output Range Problem? How to make it work?

2021-10-11 Thread Paul Backus via Digitalmars-d-learn

On Monday, 11 October 2021 at 15:57:00 UTC, apz28 wrote:
The subject is why the call is not allowed (format is not 
mention in question). Below sample is a bit more clear



[...]

ref Writer outFail(Writer, Char)(return ref Writer sink)
if (isOutputRange!(Writer, Char) && isSomeChar!Char)
{return sink;}

[...]

foo.outFail(buffer); // NOT OK


The template parameter `Char` does not appear anywhere in the 
function's parameter list, so the compiler cannot deduce it from 
the function's arguments.


Here is a simpler example that demonstrates the same problem:

```d
Dest convert(Source, Dest)(Source source)
{
return cast(Dest) source;
}

void main()
{
double d = 123.456;
auto result = convert(d); // Source = double, Dest = ???
}
```


Re: Output Range Problem? How to make it work?

2021-10-11 Thread apz28 via Digitalmars-d-learn

On Monday, 11 October 2021 at 00:37:43 UTC, Paul Backus wrote:

On Monday, 11 October 2021 at 00:19:44 UTC, apz28 wrote:

/* Getting this error
onlineapp.d(34): Error: none of the overloads of `toString` 
are callable using argument types `(Buffer)`, candidates are:

onlineapp.d(19):`onlineapp.Foo.toString()`
onlineapp.d(26):`onlineapp.Foo.toString(const(char)[] 
fmt)`
onlineapp.d(22):`toString(Writer, Char)(return ref 
Writer sink)`

*/


The signature of your `toString` method should match one of the 
examples in [the documentation][1]:


```d
void toString(Writer, Char)(ref Writer w, const ref 
FormatSpec!Char fmt)

void toString(Writer)(ref Writer w)
string toString();
```

Here is an example that works:

```d
import std.range: put;
import std.array: appender;
import std.format: formattedWrite;

struct Foo
{
void toString(Writer)(ref Writer writer)
{
put(writer, "Foo");
}
}

void main()
{
auto buffer = appender!string;
Foo foo;
formattedWrite(buffer, "%s", foo);
assert(buffer[] == "Foo");
}
```

Link: https://run.dlang.io/is/dZLRuo


[1]: https://phobos.dpldocs.info/std.format.write.html


On Monday, 11 October 2021 at 00:37:43 UTC, Paul Backus wrote:

The subject is why the call is not allowed (format is not mention 
in question). Below sample is a bit more clear


import std.range.primitives : isOutputRange;
import std.traits: isSomeChar;

@safe:

struct Buffer(Char)
{
@safe:

void put(Char c)
{}

void put(scope const(Char)[] s)
{}
}

struct Foo
{
@safe:

ref Writer outWork(Writer)(return ref Writer sink)
if (isOutputRange!(Writer, char))
{return sink;}

// Remove " && isSomeChar!Char" does not make any 
difference

ref Writer outFail(Writer, Char)(return ref Writer sink)
if (isOutputRange!(Writer, Char) && isSomeChar!Char)
{return sink;}
}

void main()
{   
pragma(msg, isOutputRange!(Buffer!char, char)); // Print 
true


Buffer!char buffer;
Foo foo;
foo.outWork(buffer); // OK

foo.outFail!(Buffer!char, char)(buffer); // OK with 
explicit


foo.outFail(buffer); // NOT OK
}


/* Blow is output from online compiler
true
onlineapp.d(40): Error: template `onlineapp.Foo.outFail` cannot 
deduce function from argument types `!()(Buffer!char)`, 
candidates are:
onlineapp.d(25):`outFail(Writer, Char)(return ref Writer 
sink)`

*/


Re: I need a detailed document about druntime.

2021-10-11 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

On Monday, 11 October 2021 at 15:24:07 UTC, Adam D Ruppe wrote:
On Monday, 11 October 2021 at 15:18:11 UTC, Ferhat Kurtulmuş 
wrote:
"Each call to initialize must be paired by a call to 
terminate.'


It is so the refcount works out.

When you call initialize, it does something like:

if(refcount == 0)
   actually intialize; // calls constructors etc
refcount++;


When you call terminate, it does:

refcount--;
if(refcount == 0)
   actually terminate; // calls destructors etc



If you don't pair it, the refcount will be off, so the next 
call to terminate will still see ref > 0 and not actually 
terminate.


The D main inserts a call to init before main and a call to 
terminate after main automatically.


That makes sense, now I see, thank you again Adam.


Re: I need a detailed document about druntime.

2021-10-11 Thread Adam D Ruppe via Digitalmars-d-learn
On Monday, 11 October 2021 at 15:18:11 UTC, Ferhat Kurtulmuş 
wrote:

"Each call to initialize must be paired by a call to terminate.'


It is so the refcount works out.

When you call initialize, it does something like:

if(refcount == 0)
   actually intialize; // calls constructors etc
refcount++;


When you call terminate, it does:

refcount--;
if(refcount == 0)
   actually terminate; // calls destructors etc



If you don't pair it, the refcount will be off, so the next call 
to terminate will still see ref > 0 and not actually terminate.


The D main inserts a call to init before main and a call to 
terminate after main automatically.


Re: I need a detailed document about druntime.

2021-10-11 Thread Ferhat Kurtulmuş via Digitalmars-d-learn

On Monday, 11 October 2021 at 15:09:12 UTC, Adam D Ruppe wrote:
On Monday, 11 October 2021 at 14:56:19 UTC, Ferhat Kurtulmuş 
wrote:
What I want is to bypass runtime initialization if it is 
already initialized.


That what it does by itself, you can call it and it has an 
internal count.


Thank you for your response. But this confuses me:

"Each call to initialize must be paired by a call to terminate.'


https://dlang.org/library/core/runtime/runtime.initialize.html


Re: I need a detailed document about druntime.

2021-10-11 Thread Adam D Ruppe via Digitalmars-d-learn
On Monday, 11 October 2021 at 14:56:19 UTC, Ferhat Kurtulmuş 
wrote:
What I want is to bypass runtime initialization if it is 
already initialized.


That what it does by itself, you can call it and it has an 
internal count.




I need a detailed document about druntime.

2021-10-11 Thread Ferhat Kurtulmuş via Digitalmars-d-learn
I want to know what happens if either Runtime.initialize or 
terminate is called without matching each other. And why there is 
no ready-to-use thing like initCount which is accessible in the 
code? What I want is to bypass runtime initialization if it is 
already initialized. The below code is my workaround, but it can 
only keep track of my initializations, not the one that 
automatically get fired where there is a dmain.


Should İ use "bool runMain" to differentiate between the 
compilations of dll and executable?


```d
private {
import core.runtime;
import core.atomic;

shared size_t initCount;

void initRT(){
if(!atomicLoad!(MemoryOrder.acq)(initCount)){
Runtime.initialize();
atomicOp!"+="(initCount, 1);
}
}

void termRT(){
if(atomicLoad!(MemoryOrder.acq)(initCount) > 0){
Runtime.terminate();
atomicOp!"-="(initCount, 1);
}
}
}
```


Re: Managing malloced memory

2021-10-11 Thread Mike Parker via Digitalmars-d-learn

On Monday, 11 October 2021 at 10:53:15 UTC, anon wrote:


S makeS(int x)
{
   return S(x); // no destructor called here.
}

void main()
{
   foo(S(1)); // no destructor called for this rvalue
   auto s = makeS(1);
   // destructor for s called here.
   foo(makeS(1)); // only one destructor called at the end of 
foo

}
```
Is there any reference for exactly how these rules apply, or is 
this implementation defined? The 
[specification](https://dlang.org/spec/struct.html#struct-destructor) says that destructors are called when objects go out of scope. Your examples seem to suggest that this is untrue in some cases.


For example, in `makeS` the initializer combined with the return 
triggers an optimization (return value optimization, or RVO)) 
that elides a copy of the struct, meaning there's nothing to 
destroy at the end of `makeS`. The destruction will occur in the 
scope into which the instance is moved.


Any time you have a named instance, like `S s = S(1)`, you can 
pretty much guarantee its destructor will be called. An exception 
is when `s` is returned immediately after the initialization, 
then NRVO (named return value optimization) can kick in to elide 
the copy and, therefore, the destruction again happens at the end 
of the scope into which the instance is moved.


Play around with a struct destructor that prints a message and 
you'll get a feel for when destructors are and aren't called. 
Like Steve said, it's once per copy. Sometimes you end up with 
temporaries that are destroyed, sometimes you don't depending on 
compiler optimizations.


Re: Managing malloced memory

2021-10-11 Thread Imperatorn via Digitalmars-d-learn

On Monday, 11 October 2021 at 12:20:27 UTC, jfondren wrote:

On Monday, 11 October 2021 at 12:09:07 UTC, Imperatorn wrote:

On Wednesday, 6 October 2021 at 18:06:38 UTC, anon wrote:
I interface to a C library that gives me a malloced object. 
How can I manage that pointer so that it gets freed 
automatically.

What I've thought of so far:
* scope(exit): not an option because I want to return that 
memory


Explain again why scope exit isn't an option


The explanation is "I want to return that memory".


```d
int* not_an_option() {
import core.memory : pureMalloc, pureFree;

int* p = cast(int*) pureMalloc(int.sizeof);
scope (exit)
pureFree(p);
return p;
}

unittest {
not_an_option()[0] = 1;
}
```

valgrind: Invalid write of size 4


Oops


Re: Managing malloced memory

2021-10-11 Thread jfondren via Digitalmars-d-learn

On Monday, 11 October 2021 at 12:09:07 UTC, Imperatorn wrote:

On Wednesday, 6 October 2021 at 18:06:38 UTC, anon wrote:
I interface to a C library that gives me a malloced object. 
How can I manage that pointer so that it gets freed 
automatically.

What I've thought of so far:
* scope(exit): not an option because I want to return that 
memory


Explain again why scope exit isn't an option


The explanation is "I want to return that memory".


```d
int* not_an_option() {
import core.memory : pureMalloc, pureFree;

int* p = cast(int*) pureMalloc(int.sizeof);
scope (exit)
pureFree(p);
return p;
}

unittest {
not_an_option()[0] = 1;
}
```

valgrind: Invalid write of size 4


Re: Managing malloced memory

2021-10-11 Thread Imperatorn via Digitalmars-d-learn

On Wednesday, 6 October 2021 at 18:06:38 UTC, anon wrote:
I interface to a C library that gives me a malloced object. How 
can I manage that pointer so that it gets freed automatically.

What I've thought of so far:
* scope(exit): not an option because I want to return that 
memory
* struct wrapper: Doesn't work because if I pass it to another 
function, they also destroy it (sometimes). Also same problem 
as with scope(exit)
* struct wrapped in automem/ refcounted: The struct still 
leaves original scope and calls the destructor


Explain again why scope exit isn't an option


Re: Managing malloced memory

2021-10-11 Thread anon via Digitalmars-d-learn
On Thursday, 7 October 2021 at 11:55:35 UTC, Steven Schveighoffer 
wrote:
The GC is technically not required to free any blocks ever. But 
in general, it does.


When it does free a struct, as long as you allocated with 
`new`, it should call the dtor.


In practice when I played around with it, destructor always got 
called by GC. But: https://dlang.org/spec/class.html#destructors 
says at point 6:
The garbage collector is not guaranteed to run the destructor 
for all unreferenced objects.
Is it the same for structs or are these destructors guaranteed to 
be called? Would it be suitable to clean up tempfiles with 
GC-managed structs?


Just FYI, you should reply to the posts that you quote, or at 
least copy the "X Y wrote" line so people understand the thread.


Alright. If I want to reply to multiple people, should I post 
twice or quote both in the same post?


The destructor is called once per copy. This is why disabling 
copy prevents double freeing.


There are cases where the compiler avoids calling the 
destructor because the instance is moved. Such as returning a 
newly constructed item (typically referred to as an "rvalue"), 
or passing a newly constructed item into a parameter. The 
parameter will be destroyed, but the call-site constructed item 
will not.


e.g.:

```d
struct S
{
   int x;
   ~this() { writeln("destructor called"); }
}

void foo(S s) {

   // destructor for s called here
}

S makeS(int x)
{
   return S(x); // no destructor called here.
}

void main()
{
   foo(S(1)); // no destructor called for this rvalue
   auto s = makeS(1);
   // destructor for s called here.
   foo(makeS(1)); // only one destructor called at the end of 
foo

}
```
Is there any reference for exactly how these rules apply, or is 
this implementation defined? The 
[specification](https://dlang.org/spec/struct.html#struct-destructor) says that destructors are called when objects go out of scope. Your examples seem to suggest that this is untrue in some cases.


Re: How to "stringnify"?

2021-10-11 Thread bauss via Digitalmars-d-learn

On Sunday, 10 October 2021 at 09:51:27 UTC, rempas wrote:

On Sunday, 10 October 2021 at 08:48:21 UTC, Imperatorn wrote:


For simple stuff you have .stringof


Thanks!


Just remember .stringof is not "literal" as in there are certain 
expression that won't return exactly what you're trying to 
"stringify" ex. aliases etc. will actually return what they're an 
alias of etc. there are many other exceptions too.


In general it will return just what you write, but not in all 
cases.