www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Help on array pointers

reply Vino <akashvino79 gmail.com> writes:
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
Sep 14 2023
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
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
Sep 14 2023
parent reply Vino <akashvino79 gmail.com> writes:
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"])); } ```
Sep 14 2023
parent vino <akashvino79 gmail.com> writes:
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.
Sep 14 2023
prev sibling parent reply Joe bloow.edu <Joe bloow.edu> writes:
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. }
Sep 14 2023
parent reply Vino <akashvino79 gmail.com> writes:
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 ```
Sep 15 2023
parent reply Vino <akashvino79 gmail.com> writes:
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
Sep 15 2023
parent reply Joe bloow.edu <Joe bloow.edu> writes:
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
Sep 17 2023
parent reply vino <akashvino79 gmail.com> writes:
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.
Sep 17 2023
parent Joe bloow.edu <Joe bloow.edu> writes:
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.
Sep 22 2023