Thread overview
Help on array pointers
Sep 14
Vino
Sep 14
Vino
Sep 15
vino
Sep 15
Joe
Sep 15
Vino
Sep 15
Vino
Sep 17
Joe
Sep 18
vino
Sep 22
Joe
September 14

Hi All,

Request your help to guide me in understanding about pointers, the below code works,I have few question which i need your help for better understanding.

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]";

Question:2

char[]* invalidptr = &invalid;

Is this the right way to create a array pointer.

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.

Question: 4
Who do we free the memory allocated.
Code:

auto ref testNames(in string[] names) {
	enforce(!empty(names), "Names cannot be Empty or Null");
		
	import core.stdc.stdlib;
        import std.algorithm: any, canFind;
       		
	size_t length = 20;
	char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length];
	char[]* invalidptr = &invalid;
		
	version(Windows) { (*invalidptr) = ['\'','\"',':',';','*','&','[',']','-','+','$','#','<','>','{','}','(',')']; }
					
	foreach(i; names.dup) {
		auto result = i.any!(a => (*invalidptr).canFind(a));
		if(result) { throw new Exception("Invalid Name passed: %s".format(i)); }
		}
		string[] _names = names.dup;
		return _names;
	}

From,
Vino

September 14

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.

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, which may cause your program to crash or behave unpredictably.

September 14

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.

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, which may cause your program to crash or behave unpredictably.

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"]));
}


September 15

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.

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, which may cause your program to crash or behave unpredictably.

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.
September 15

On Thursday, 14 September 2023 at 14:21:09 UTC, Vino wrote:

>

Hi All,

Request your help to guide me in understanding about pointers, the below code works,I have few question which i need your help for better understanding.

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]";

Question:2

char[]* invalidptr = &invalid;

Is this the right way to create a array pointer.

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.

Question: 4
Who do we free the memory allocated.
Code:

auto ref testNames(in string[] names) {
	enforce(!empty(names), "Names cannot be Empty or Null");
		
	import core.stdc.stdlib;
        import std.algorithm: any, canFind;
       		
	size_t length = 20;
	char[] invalid = (cast(char*)malloc(char.sizeof * length))[0..length];
	char[]* invalidptr = &invalid;
		
	version(Windows) { (*invalidptr) = ['\'','\"',':',';','*','&','[',']','-','+','$','#','<','>','{','}','(',')']; }
					
	foreach(i; names.dup) {
		auto result = i.any!(a => (*invalidptr).canFind(a));
		if(result) { throw new Exception("Invalid Name passed: %s".format(i)); }
		}
		string[] _names = names.dup;
		return _names;
	}

From,
Vino

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.

https://run.dlang.io/gist/19c63d325ee412df23bdbefabce111b9

import std, std.stdio, core.stdc.stdlib;

void main()
{
   	float x = 43.534f;  // Creates a float type that hold sthe value 43.534
    writeln("Value of x = ", x); // Displays it's value
    writeln("Address of x = ", &x); // Displays it's address

    writeln();
    float* y = null; // creates a pointer of type float note that it is point to no memory location(null) and so it is an error to store a value to the location

    writeln("Value of y = ", y); // Displays it's address(remember, y is a ptr to a float, not a float)

    y = new float(); // This allocates free/unused memory(of float type) to y so we can store a value.
    *y = 50.34f; // assigns it the value 50.34. We have to use * because if we didn't we would be trying to change the address of y

    writeln("Value of y = ", y); // Displays it's address(remember, y is a ptr to a float, not a float)
    writeln("Address of y = ", &y); // Writes it's address(y is a pointer but it also is stored in a location in memory and hence has an address
    writeln("Dereferenced value of y = ", *y); // Displays the value y is pointing to interpreting it as a float(the base type of the pointer)

    writeln("Dereferences the value of y as if it were an int = ", *(cast(int*)y)); // Displays the value y is pointing to interpreting it as a int. We have to force the compilier to reinterpret it as an int*.

    writeln();
    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.

    writeln("Value of z = ", z); // Displays it's address(remember, z is a ptr to a float, not a float)
    writeln("Address of z = ", &z); // Note that z is an array but it is a pointer to and &z gets the address where the "array" is stored.
    writeln("Value of z's pointer = ", z.ptr); // Displays it's address(remember, y is a ptr to a float, not a float)
    writeln("Length of z = ", z.length); // Writes it's address(y is a pointer but it also is stored in a location in memory and hence has an address

    writeln();

    z ~= 4; // We can store/append a value to our array. The compiler will take care of dealing with allocating memory and all that.
    writeln("Value of z = ", z); // Displays it's address(remember, z is a ptr to a float, not a float)
    writeln("Address of z = ", &z); // Note that z is an array but it is a pointer to and &z gets the address where the "array" is stored.
    writeln("Value of z's pointer = ", z.ptr); // Displays it's address(remember, y is a ptr to a float, not a float)
    writeln("Length of z = ", z.length); // Writes it's address(y is a pointer but it also is stored in a location in memory and hence has an address

    z ~= 54; // We can store/append a value to our array. The compiler will take care of dealing with allocating memory and all that.
    writeln("Value of z = ", z); // Displays it's address(remember, z is a ptr to a float, not a float)
    writeln("Address of z = ", &z); // Note that z is an array but it is a pointer to and &z gets the address where the "array" is stored.
    writeln("Value of z's pointer = ", z.ptr); // Displays it's address(remember, y is a ptr to a float, not a float)
    writeln("Length of z = ", z.length); // Writes it's address(y is a pointer but it also is stored in a location in memory and hence has an address

    z ~= 14; // We can store/append a value to our array. The compiler will take care of dealing with allocating memory and all that.
    writeln("Value of z = ", z); // Displays it's address(remember, z is a ptr to a float, not a float)
    writeln("Address of z = ", &z); // Note that z is an array but it is a pointer to and &z gets the address where the "array" is stored.
    writeln("Value of z's pointer = ", z.ptr); // Displays it's address(remember, y is a ptr to a float, not a float)
    writeln("Length of z = ", z.length); // Writes it's address(y is a pointer but it also is stored in a location in memory and hence has an address
    writeln("\nNotice now that the value of z's pointer is not null but some address, the reason is that the compiler allocated the memory for us so we would not get an exception trying to write to unallocated memory.\n");

    // 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);

	*(q+0) = 4; // Store a value at the first entry of q;
    *(q+1) = 54; // Store a value at the second entry of q;
    *(q+2) = 14; // Store a value at the third entry of q;

    writeln(*(q+1));

    writeln(*cast(ushort*)(q)); // We temporarily turned q in to a ushort pointer and then got it's value(it's the same as the first since this is effectively  just casting an int to a short and 4 fits in both.




}
September 15

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
September 15

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
September 17

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; 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;
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

September 18

On Sunday, 17 September 2023 at 18:28:36 UTC, Joe wrote:

>

On Friday, 15 September 2023 at 16:55:34 UTC, Vino wrote:

> >

[...]

>

[...]

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".

[...]

Thank you very much, I am still newbie for programming and currently concentrating on Arrays/Struct/Pointers/Memory management.

September 22

On Monday, 18 September 2023 at 02:49:37 UTC, vino wrote:

>

On Sunday, 17 September 2023 at 18:28:36 UTC, Joe wrote:

>

On Friday, 15 September 2023 at 16:55:34 UTC, Vino wrote:

> >

[...]

>

[...]

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".

[...]

Thank you very much, I am still newbie for programming and currently concentrating on Arrays/Struct/Pointers/Memory management.

It will make more sense over time. It's actually really simple but it takes time to get used to thinking along the lines of the computer languages and such.

My suggestion is simply do a lot of examples. Just type them in. As you type you think about what you are typing and how it relates. Then you will start to notice the patterns and such.

I wouldn't try to create new programs from scratch because it's easy to make mistakes that can be very hard to debug.

D might not be the best language to start learning programming.

E.g., might be better to go with javascript, lua, or python and get a nice rapid development environment. Even though D is fast to compile it's not that fast.

Maybe use Repl which lets you code line by line essentially. All languages more or less are the same but just look different so it you want to find out one that has the most convenience. you don't want to bite off too much as it will slow you down.

Ultimately it's just like anything else though in that you are learning a language and all it's nuances. You ultimately have to learn how to translate your thoughts and desires in to the correct syntax so you can make the language useful and act as a tool. If you try to us it as a tool before you learn to mimic others it will be very slow and frustrating.

Because most languages are 99% the same with just different syntax(just about every major programming language can do what ever other one can, it's just some are better/easier at doing certain things than others).

You might try learning several languages at once as it can actually speed things up.

Learn how to write simple programs(hello worlds) then modify those to do more and then learn control structures(branching(if's), loops(for)), variables, etc. Build up slowly and everything will make sense. Build up fast and you'll get lost at some point and then spend a lot of time trying to figure out how to make sense of it.

Ideally you want an ide and language that gives you precise info on errors that you make else it can be hard to track down mistakes because sometimes errors can be hidden. D is not good for.

Even Q-basis might be better to start with or try to find Turbo Pascal if it still exists.

What makes D great is it's generic/template programming and that is a more complex topic that you probably won't get much in to for a few years(although it is not really hard it will seem like it at first).

D has a lot of features that hard core programmers like and so you are not going to be using those features for a while so it might not be worth using D to learn off of.

Not saying you can't do it but it might be slow. You could always do it in parallel. E.g., learn to write simple programs in many languages then build up.

E.g.,

for i=1:10 // Matlab
for(auto i = 1; i < 10; i++) // D
for(int i = 1; i < 10; i++) // C
for(var i = 1; i < 10; i++) // JS
for i from 1 to 10 // maple
loop(50, ...) // JSFX
for i = 1,10 // lua

etc.

The underlying idea is that one wants a way to do the same thing over and over and so loops exist to handle that pattern. Each language uses different ways to express a loop. Just like languages, all languages uses nouns, verbs, etc but express them differently.