Help on array pointers

Joe at bloow.edu Joe at bloow.edu
Sun Sep 17 18:28:36 UTC 2023


On Friday, 15 September 2023 at 16:55:34 UTC, Vino wrote:
> On Friday, 15 September 2023 at 15:27:00 UTC, Vino wrote:
>> On Friday, 15 September 2023 at 02:25:09 UTC, Joe wrote:
>>> On Thursday, 14 September 2023 at 14:21:09 UTC, Vino wrote:
>>>> [...]
>>>
>>> A pointer is a type that points to something. It's literally 
>>> that simple. Every piece of data and code exist somewhere in 
>>> memory. Every piece of memory has an address. The address is 
>>> what a pointer contains. Sometimes we want a type that is the 
>>> address itself rather than a value/number.
>>>
>>> [...]
>>
>> Hi Joe,
>> Thank you very much for the explanation can you please correct 
>> me if my understanding is incorrect
>> ```
>> byte[] z; // Creates an array of bytes. That is, the compiler 
>> will create a pointer to an array of memory and track it's 
>> length and deal with memory allocation and all that.
>> ```
>> If we use the above method then :

>> The compiler takes care of initilizing the array and free the 
>> memory after the usage.
>> And this is the recommended method.
>>
>> ```
>> We can use a pointer as an array also, this is the "old school 
>> way of creating arrays".
>>     int qlen = 5;
>>     int* q = cast(int*)malloc(int.sizeof*qlen);
>> ```	
>> If we use the above method then :
>> We need to manual initilize the array.
>> Ensure that the memory is freed after the usage using 
>> try/final block.
>>
>> By default the memory allocation for arrays in D is based on 
>> GC (expect for std.array containers) if we want to 
>> reduce/avoid GC then we need to use the old school way of 
>> creating the arrays.
>>
>> In case of using the old school ways then can you guide me 
>> what is wrong in my earlier code that I am getting the below 
>> error and how do I correct the same.
>>
>> Error
>> ```
>> Invalid Name passed: /T&name
>> double free or corruption (out)
>> Error: program killed by signal 6
>> ```
>
> Hi All,
>
>      At last was able to resolve the issue, but not sure 
> whether this is the reight solution.
>
> 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 len = 19;
>      char[] invalid = (cast(char*)malloc(char.sizeof * 
> len))[0..len];
>      invalid[0 ..len] = 0; //Array Initlization
>         		
>      try {
>            version(Posix) {
>               invalid = 
> ['\'','\"',':',';','*','&','/','[',']','-','+','$','#','<','>','{','}','(',')'];
>           }
>
>           foreach(i; names.dup) {
>           auto result = i.any!(a => invalid.canFind(a));
>           if(result) { throw new Exception("Invalid Name 
> passed: %s".format(i)); }
>           else {_names = names.dup; return _names; }
>           }
>         } catch(Exception e) { writeln(e.msg);  }
>           finally { invalid = null; free(invalid.ptr); } // 
> added invalid = null resolved the issue
>          return _names;
>     }
>
>     void main () {
>         writeln(testNames(["/T&name"]));
>     }
>
> From,
> Vino


char[] invalid = (cast(char*)malloc(char.sizeof * len))[0..len];

This is not the way to go about it. You are mixing "pointer 
arrays" with "arrays".

You are creating a pointer array then turning that in to an 
array. There is no need to do that. Basically you are copying 
what the compiler already does for you.

When you are using arrays([] language) you don't have to worry 
about anything. Just use them as arrays directly and let the 
compiler deal with memory management. The entire point of 
"managed arrays" is to avoid having to manually deal with memory 
which can cause problems if one is not careful.

Of course you have to make sure your array used used correctly 
but that should be obvious.



char[] invalid = (cast(char*)malloc(char.sizeof * len))[0..len];

is exactly the same as

char[] invalid. EXCEPT that you've forced it to be initialized 
with a length of len and went from D in to C then back to D just 
to create an array. You are making it much more complex than it 
needs to be. There are good tutorials on D arrays that you should 
look over. You will see how easy they are.

You could just do char[] invalid = new char[](len); for the same 
effect but is nicer. New understands char, malloc only 
understands bytes. You should not use malloc in D unless you 
explicitly know you need to use it. Malloc is primitive memory 
management.

When you use D's symantics for arrays it is much easier... which 
is the entire point. You don't even need to free the arrays. D 
knows they are local variable sand will free them when out of 
scope. It will grow them when they need to grow, etc.

invalid = null; free(invalid.ptr);

That does nothing. you set invalid.ptr to null and are freeing 
null so you are not freeing the array.

You don't have to though, the array will be free out of scope(not 
in final though so exceptions could cause memory leak) because it 
is a D array.

Do not use free or malloc in your D programs until you understand 
D arrays.  You are making it much harder on yourself. The entire 
point of D arrays is to be simpler and take all the trouble out 
of pointer arrays.

// This creates an array of chars of length 6(it can change if we 
append)
     char[] A = new char[](6);
     A[0..$] = 'a'; // initializes all entries to 'a'
     writeln(A[4]); // shows that the 5th entry is 'a'

We don't have to worry about freeing up the array, D will do it 
for us.


https://dlang.org/spec/arrays.html



More information about the Digitalmars-d-learn mailing list