www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Unable to open filename passed as command line argument

reply Curious <curiour home.com> writes:
Given the following:

=====a======
void main(string[] args)
{
     FILE* fp = fopen(args[1].ptr, "r");
     if (!fp) throw new Exception("fopen");
}

=====b======
void main(string[] args)
{
     FILE* fp = fopen(args[1].dup.ptr, "r");
     if (!fp) throw new Exception("fopen");
}

Why does a fail but b succeed?
Sep 03 2020
next sibling parent drug <drug2004 bk.ru> writes:
On 9/3/20 1:47 PM, Curious wrote:
 Given the following:
 
 =====a======
 void main(string[] args)
 {
      FILE* fp = fopen(args[1].ptr, "r");
      if (!fp) throw new Exception("fopen");
 }
 
 =====b======
 void main(string[] args)
 {
      FILE* fp = fopen(args[1].dup.ptr, "r");
      if (!fp) throw new Exception("fopen");
 }
 
 Why does a fail but b succeed?
try `toStringz`: ```D import std.string : toStringz; void main(string[] args) { FILE* fp = fopen(args[1].toStringz, "r"); if (!fp) throw new Exception("fopen"); } ``` The reason is that args are D strings (that contains no terminating 0) but `fopen` gets C string (null terminated) so your `a` variant fails because the filename becomes wrong as there is no terminating 0. Your `b` variant works in fact accidentally because after duplication in new memory after filename 0 appears due to random reason (for example all that memory area zeroed by allocator).
Sep 03 2020
prev sibling parent reply user1234 <user1234 12.de> writes:
On Thursday, 3 September 2020 at 10:47:04 UTC, Curious wrote:
 Given the following:

 =====a======
 void main(string[] args)
 {
     FILE* fp = fopen(args[1].ptr, "r");
     if (!fp) throw new Exception("fopen");
 }

 =====b======
 void main(string[] args)
 {
     FILE* fp = fopen(args[1].dup.ptr, "r");
     if (!fp) throw new Exception("fopen");
 }

 Why does a fail but b succeed?
version b works by accident/UB. You need to null terminate your filename if you use the C library functions: --- void main(string[] args) { FILE* fp = fopen((args[1] ~ '\0').ptr, "r"); if (!fp) throw new Exception("fopen"); } --- otherwise what you get as args are D dynamic arrays (a payload made of .ptr and .length) so you can use std.file or std.stdio to open a file using the "D main" arguments (it's not the like "C main"). --- void main(string[] args) { import std.stdio; File f = File(args[1], "r"); } ---
Sep 03 2020
parent Curious <curiour home.com> writes:
On Thursday, 3 September 2020 at 11:12:49 UTC, user1234 wrote:
 On Thursday, 3 September 2020 at 10:47:04 UTC, Curious wrote:

 otherwise what you get as args are D dynamic arrays (a payload 
 made of .ptr and .length) so you can use std.file or std.stdio 
 to open a file using the "D main" arguments (it's not the like 
 "C main").

 ---
 void main(string[] args)
 {
     import std.stdio;
     File f = File(args[1], "r");
 }
 ---
Okay. Got it! Thanks
Sep 03 2020