malloc error when trying to assign the returned pointer to a struct field

Hipreme msnmancini at hotmail.com
Fri Sep 8 09:25:59 UTC 2023


On Friday, 8 September 2023 at 07:59:37 UTC, rempas wrote:
> I do have the following struct:
>
> ```d
> struct Vec(T) {
> private:
>   T* _ptr = null; // The pointer to the data
>   u64 _cap = 0;   // Total amount of elements (not bytes) we 
> can store
>
> public:
>   /* Create a vector by just allocating memory for it. The null 
> terminator is not set for
>      strings as, the vector is considered empty and we should  
> first push something to it
>      in order to use it! */
>   this(i64 size) {
>     this._len = 0;
>     this._cap = size;
>
>     static if (is(T == char)) { size += 1; } // Additional 
> space for the null terminator
>     this._ptr = cast(T*)malloc(size);
>   }
> }
> ```
>
> That's some minimal code that I do have just to showcase it. 
> So, some times, this work will works, some others, it will give 
> me the following error:
>
> `Fatal glibc error: malloc.c:2594 (sysmalloc): assertion 
> failed: (old_top == initial_top (av) && old_size == 0) || 
> ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) 
> && ((unsigned long) old_end & (pagesize - 1)) == 0)`
>
> The problem seems to happen when the pointer that is returned 
> from `malloc` is assigned to the `_ptr` field. If I just assign 
> it to a variable and don't assign anything to `_ptr`, it will 
> work!
>
> Is there any possible that there is a compiler bug? I do use 
> ldc2 and `betterC`!



Hello, not completely unrelated to your problem, I have also done 
something like that, and when you're in D, don't use simply a 
pointer and length like that, use the `slice` operator.

See references:

https://tour.dlang.org/tour/en/basics/slices
https://dlang.org/spec/operatoroverloading.html#array-ops


For example, you can make your pointer a lot safer by doing:

```d
size_t length = 5;
int* pointer = cast(int*)malloc(int.sizeof * length); //Don't
int[] mallocArray = (cast(int*)malloc(int.sizeof * 
length))[0..length]; //Do
```

On the second way, you'll get bound checks, thus, making it 
safer. Also, no need to keep track of your length separately 
anymore.

This is good practice in D language and you'll find yourself 
using this instead in the future.

And yes, this works in betterC, it is a simple runtime check, 
completely `@nogc @safe nothrow` and every other kind of thing 
you would want.


More information about the Digitalmars-d-learn mailing list