digitalmars.D.learn - Manually allocating a File
- Chris M. (21/21) Feb 20 2018 I'm doing this mainly for experimentation, but the following
- Adam D. Ruppe (23/30) Feb 20 2018 so important note: this will perform worse than the automatic
- Chris M. (16/42) Feb 20 2018 Thanks for the info, that clears things up. Like I said, it was
- Nicholas Wilson (3/26) Feb 20 2018 FYI, File is a reference counted FILE* so theres not really any
- Jonathan M Davis (8/40) Feb 20 2018 And worse, simply calling free does not run the File's destructor, so si...
- Steven Schveighoffer (5/8) Feb 21 2018 More FYI, the reference counted payload is actually allocated on the C
- Uknown (18/39) Feb 20 2018 File * is a C standard library type. You mixed the C standard
- Uknown (2/5) Feb 20 2018 Never mind, I confused FILE* with File...
I'm doing this mainly for experimentation, but the following piece of code gives all sorts of errors. Hangs, segfaults or prints nothing and exits import std.stdio; import core.stdc.stdlib; void main() { auto f = cast(File *) malloc(File.sizeof); *f = File("test.txt", "r"); (*f).readln.writeln; // freeing is for chumps } I could have sworn I've done something similar recently and it worked, unfortunately I can't remember what the case was. This is what gdb gave me on a segfault Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7a56c32 in _D2rt5minfo__T17runModuleFuncsRevSQBgQBg11ModuleGroup8runDtorsMFZ9__lambda1ZQCkMFAxPyS6 bject10ModuleInfoZv () from /usr/lib64/libphobos2.so.0.78 So it looks like it's reaching the end of main. Past that I can't tell what's going on. Ideas?
Feb 20 2018
On Tuesday, 20 February 2018 at 14:56:54 UTC, Chris M. wrote:I'm doing this mainly for experimentation, but the following piece of code gives all sorts of errors.so important note: this will perform worse than the automatic allocation, which just puts it down in-place. You should basically never `new` or `malloc` a `File` struct. (in fact, i think we should disable new on it! yes, D can do that!)auto f = cast(File *) malloc(File.sizeof); *f = File("test.txt", "r");Two notes here: 1) it will call the destructor on *f, which is uninitialized data and 2) the destructor that actually wants to run will have to wait until the GC reaps it, which is also not exactly what is causing it, could be out-of-order, could be some other corruption, idk. Generally, when manually allocating D objects, first malloc it, then copy the `.init` value over, before casting it to the other type - do all this as bytes so it doesn't trigger postblits, destructors, etc like a real struct. The `std.conv.emplace` function from phobos does this and its source code can help you see how in a few cases.(*f).readln.writeln;That * is unnecessary btw, in D you can f.readln and it will see it is a pointer to struct and dereference it for you.I could have sworn I've done something similar recently and it worked, unfortunately I can't remember what the case was.With other types, you can do this, but File is designed to be used in-place...
Feb 20 2018
On Tuesday, 20 February 2018 at 15:18:11 UTC, Adam D. Ruppe wrote:On Tuesday, 20 February 2018 at 14:56:54 UTC, Chris M. wrote:Thanks for the info, that clears things up. Like I said, it was more experimentation rather than me planning to actually use it. Works now with the following modifications. import std.stdio; import core.stdc.stdlib; import std.conv; void main() { auto f = cast(File*) malloc(File.sizeof); emplace!File(f, "test.txt", "r"); f.readln.write; free(f); }I'm doing this mainly for experimentation, but the following piece of code gives all sorts of errors.so important note: this will perform worse than the automatic allocation, which just puts it down in-place. You should basically never `new` or `malloc` a `File` struct. (in fact, i think we should disable new on it! yes, D can do that!)auto f = cast(File *) malloc(File.sizeof); *f = File("test.txt", "r");Two notes here: 1) it will call the destructor on *f, which is uninitialized data and 2) the destructor that actually wants to run will have to wait until the GC reaps it, which is also not exactly what is causing it, could be out-of-order, could be some other corruption, idk. Generally, when manually allocating D objects, first malloc it, then copy the `.init` value over, before casting it to the other type - do all this as bytes so it doesn't trigger postblits, destructors, etc like a real struct. The `std.conv.emplace` function from phobos does this and its source code can help you see how in a few cases.That's what I had originally, but I put the * in to see if it would help with the original issue and never removed it(*f).readln.writeln;That * is unnecessary btw, in D you can f.readln and it will see it is a pointer to struct and dereference it for you.
Feb 20 2018
On Tuesday, 20 February 2018 at 15:32:45 UTC, Chris M. wrote:Thanks for the info, that clears things up. Like I said, it was more experimentation rather than me planning to actually use it. Works now with the following modifications. import std.stdio; import core.stdc.stdlib; import std.conv; void main() { auto f = cast(File*) malloc(File.sizeof); emplace!File(f, "test.txt", "r"); f.readln.write; free(f); }FYI, File is a reference counted FILE* so theres not really any point of heap allocating it.That's what I had originally, but I put the * in to see if it would help with the original issue and never removed it(*f).readln.writeln;That * is unnecessary btw, in D you can f.readln and it will see it is a pointer to struct and dereference it for you.
Feb 20 2018
On Wednesday, February 21, 2018 02:59:21 Nicholas Wilson via Digitalmars-d- learn wrote:On Tuesday, 20 February 2018 at 15:32:45 UTC, Chris M. wrote:And worse, simply calling free does not run the File's destructor, so simply using malloc to allocate it and free to free is not going to result in File functioning properly. If someone were going to just use the C API and not use std.stdio.File, then using malloc and free with FILE might make sense, but it really doesn't make sense with File. - Jonathan M DavisThanks for the info, that clears things up. Like I said, it was more experimentation rather than me planning to actually use it. Works now with the following modifications. import std.stdio; import core.stdc.stdlib; import std.conv; void main() { auto f = cast(File*) malloc(File.sizeof); emplace!File(f, "test.txt", "r"); f.readln.write; free(f); }FYI, File is a reference counted FILE* so theres not really any point of heap allocating it.That's what I had originally, but I put the * in to see if it would help with the original issue and never removed it(*f).readln.writeln;That * is unnecessary btw, in D you can f.readln and it will see it is a pointer to struct and dereference it for you.
Feb 20 2018
On 2/20/18 9:59 PM, Nicholas Wilson wrote:FYI, File is a reference counted FILE* so theres not really any point of heap allocating it.More FYI, the reference counted payload is actually allocated on the C heap :) So you are wasting a lot of effort to do something that is already done. -Steve
Feb 21 2018
On Tuesday, 20 February 2018 at 14:56:54 UTC, Chris M. wrote:I'm doing this mainly for experimentation, but the following piece of code gives all sorts of errors. Hangs, segfaults or prints nothing and exits import std.stdio; import core.stdc.stdlib; void main() { auto f = cast(File *) malloc(File.sizeof); *f = File("test.txt", "r"); (*f).readln.writeln; // freeing is for chumps } I could have sworn I've done something similar recently and it worked, unfortunately I can't remember what the case was. This is what gdb gave me on a segfault Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7a56c32 in _D2rt5minfo__T17runModuleFuncsRevSQBgQBg11ModuleGroup8runDtorsMFZ9__lambda1ZQCkMFAxPyS6 bject10ModuleInfoZv () from /usr/lib64/libphobos2.so.0.78 So it looks like it's reaching the end of main. Past that I can't tell what's going on. Ideas?File * is a C standard library type. You mixed the C standard library and D standard library in a way that would not work. The correct way to initialize a File*: void main() { import core.stdc.stdlib; auto F = fopen("test.txt", "r"); scope_exit(fclose(f)); //Reading from the file: char[100] str; fgets(&s[0], s.length, f); } Honestly speaking though you should avoid using the C library when you can use th D standard library. You can read more on the C standard library and how to use it here: http://en.cppreference.com/w/c/io
Feb 20 2018
On Tuesday, 20 February 2018 at 15:21:59 UTC, Uknown wrote:On Tuesday, 20 February 2018 at 14:56:54 UTC, Chris M. wrote: void main() [snip]Never mind, I confused FILE* with File...
Feb 20 2018