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.

Reply via email to