Help on array pointers

vino akashvino79 at gmail.com
Fri Sep 15 01:45:46 UTC 2023


On Thursday, 14 September 2023 at 17:23:53 UTC, Vino wrote:
> On Thursday, 14 September 2023 at 15:33:45 UTC, Paul Backus 
> wrote:
>> On Thursday, 14 September 2023 at 14:21:09 UTC, Vino wrote:
>>> Questions:1
>>> ```
>>> char[] invalid = (cast(char*)malloc(char.sizeof * 
>>> length))[0..length];
>>> ```
>>> The above statement allocate memory for char type and the 
>>> size of the allocated memory is char.sizeof * length so what 
>>> is the use of this "[0..length]";
>>
>> The difference between a `char*` and a `char[]` is that the 
>> `char[]` includes both the pointer and the length in the same 
>> variable. The slicing operator `[0 .. length]` is used to 
>> combine the pointer and the length into a single `char[]` 
>> variable.
>>
>> Strictly speaking, you don't *have* to do this--you could 
>> leave the pointer and the length in separate variables, and 
>> the program would still work. Most D programmers prefer to 
>> combine them because it's more convenient and less error-prone 
>> (for example, it makes it much harder to accidentally use the 
>> wrong length).
>>
>>> Question:2
>>> ```
>>> char[]* invalidptr = &invalid;
>>> ```
>>> Is this the right way to create a array pointer.
>>
>> It depends on what you mean by "array pointer".
>>
>> A `char[]` contains a pointer and a length. A `char[]*` is a 
>> pointer to a thing that contains a pointer and a length. In 
>> order to get from a `char[]*` to the actual `char` data, you 
>> have to follow *two* pointers. In that sense, you can think of 
>> `char[]*` in D as similar to `char**` in C.
>>
>>> Question: 3
>>> ```
>>> ST1: char[] invalid = (cast(char*)malloc(char.sizeof * 
>>> length))[0..length];
>>> ST2: char[]* invalid = (cast(char*)malloc(char.sizeof * 
>>> length))[0..length];
>>> ```
>>> What is the difference between the above to statement.
>>
>> The first statement is valid code and the second one isn't.
>>
>>> Question: 4
>>> Who do we free the memory allocated.
>>> Code:
>>> [...]
>>
>> In order to ensure that the memory is freed correctly even 
>> when an exception is thrown, you can use a [`try`/`finally` 
>> block.][1]
>>
>>     char[] a = (cast(char*) malloc(char.sizeof * length))[0 .. 
>> length];
>>
>>     try {
>>         doSomethingWith(a);
>>     } finally {
>>       free(a.ptr);
>>     }
>>
>> However, this by itself will not fix the code in your example 
>> because it has another serious mistake: it does not initialize 
>> the memory allocated by `malloc`. Attempting to read from 
>> uninitialized memory results in [undefined behavior][2], which 
>> may cause your program to crash or behave unpredictably.
>>
>> [1]: 
>> http://ddili.org/ders/d.en/exceptions.html#ix_exceptions.try
>> [2]: https://c-faq.com/ansi/undef.html
>
> Hi Pual,
>
>        Thank you very much for the explanation, based on your 
> statement i modifiyed the code as below, and now ti dose not 
> throw the exception where it should throw exception
>
>     Code:
>     ```
>     import std.stdio: writeln;
>     import std.exception: enforce;
>     import std.range: empty;
>     import std.format: format;
>     auto ref testNames(in string[] names) {
>         enforce(!empty(names), "Names cannot be Empty or Null");
>     		
>     	import core.stdc.stdlib;
>     	import std.algorithm: any, canFind;
>     		
>     	string[] _names;
>     	size_t length = 20;
>     	char[] invalid = (cast(char*)malloc(char.sizeof * 
> length))[0..length];
>         invalid[0 ..length] = 0;
>     		
>     	try
>     		{
>     			version(Windows) { invalid = 
> ['\'','\"',':',';','*','&','[',']','-','+','$','#','<','>','{','}','(',')']; }
>     			foreach(i; names.dup) {
>     				auto result = i.any!(a => invalid.canFind(a));
>     				if(result) { throw new Exception("Invalid Name passed: 
> %s".format(i)); }
>                  }
>     		}	catch(Exception e) { writeln(e.msg);  }
>         			finally { free(invalid.ptr);  }
>          	_names = names.dup;
>         	return _names;
>     }
>
> void main () {
> writeln(testNames(["/T&name"]));
> }
> ```

Hi All,

      Was able to find out the issue, and now it is throwing both 
the exception and another error message as below 
https://run.dlang.io/is/VZeOOj

Error:
```
Invalid Name passed: /T&name
double free or corruption (out)
Error: program killed by signal 6
```

Code:
```
import std.stdio: writeln;
import std.exception: enforce;
import std.range: empty;
import std.format: format;

     auto ref testNames(in string[] names) {
         enforce(!empty(names), "Names cannot be Empty or Null");
     		
     	import core.stdc.stdlib;
     	import std.algorithm: any, canFind;
     		
     	string[] _names;
     	size_t length = 20;
     	char[] invalid = (cast(char*)malloc(char.sizeof * 
length))[0..length];
             invalid[0 ..length] = 0;
     		
     	try
     		{
     			invalid = 
['\'','\"',':',';','*','&','[',']','-','+','$','#','<','>','{','}','(',')'];
     			foreach(i; names.dup) {
     				auto result = i.any!(a => invalid.canFind(a));
     				if(result) { throw new Exception("Invalid Name passed: 
%s".format(i)); }
                  }
     		} catch(Exception e) { writeln(e.msg);  } finally { 
free(invalid.ptr);  }	
          	_names = names.dup;
         	return _names;
     }
     void main () {
     writeln(testNames(["/T&name"]));
     }
     ```
     From,
     Vino.


More information about the Digitalmars-d-learn mailing list